xref: /llvm-project/llvm/unittests/tools/llvm-cfi-verify/GraphBuilder.cpp (revision 3b34c117db175ae6a1404f7c07857c4aa6fc1ae3)
199fa1405SMitch Phillips //===- llvm/unittests/llvm-cfi-verify/GraphBuilder.cpp --------------===//
299fa1405SMitch Phillips //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
699fa1405SMitch Phillips //
799fa1405SMitch Phillips //===----------------------------------------------------------------------===//
899fa1405SMitch Phillips 
999fa1405SMitch Phillips #include "../tools/llvm-cfi-verify/lib/GraphBuilder.h"
1099fa1405SMitch Phillips #include "../tools/llvm-cfi-verify/lib/FileAnalysis.h"
1199fa1405SMitch Phillips #include "gmock/gmock.h"
1299fa1405SMitch Phillips #include "gtest/gtest.h"
1399fa1405SMitch Phillips 
1499fa1405SMitch Phillips #include "llvm/BinaryFormat/ELF.h"
15db29f437Sserge-sans-paille #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
1699fa1405SMitch Phillips #include "llvm/MC/MCAsmInfo.h"
1799fa1405SMitch Phillips #include "llvm/MC/MCContext.h"
1899fa1405SMitch Phillips #include "llvm/MC/MCDisassembler/MCDisassembler.h"
1999fa1405SMitch Phillips #include "llvm/MC/MCInst.h"
2099fa1405SMitch Phillips #include "llvm/MC/MCInstPrinter.h"
2199fa1405SMitch Phillips #include "llvm/MC/MCInstrAnalysis.h"
2299fa1405SMitch Phillips #include "llvm/MC/MCInstrDesc.h"
2399fa1405SMitch Phillips #include "llvm/MC/MCInstrInfo.h"
2499fa1405SMitch Phillips #include "llvm/MC/MCObjectFileInfo.h"
2599fa1405SMitch Phillips #include "llvm/MC/MCRegisterInfo.h"
2699fa1405SMitch Phillips #include "llvm/MC/MCSubtargetInfo.h"
2789b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
2899fa1405SMitch Phillips #include "llvm/Object/Binary.h"
2999fa1405SMitch Phillips #include "llvm/Object/COFF.h"
3099fa1405SMitch Phillips #include "llvm/Object/ELFObjectFile.h"
3199fa1405SMitch Phillips #include "llvm/Object/ObjectFile.h"
3299fa1405SMitch Phillips #include "llvm/Support/Casting.h"
3399fa1405SMitch Phillips #include "llvm/Support/CommandLine.h"
3499fa1405SMitch Phillips #include "llvm/Support/Error.h"
3599fa1405SMitch Phillips #include "llvm/Support/MemoryBuffer.h"
3699fa1405SMitch Phillips #include "llvm/Support/TargetSelect.h"
3799fa1405SMitch Phillips #include "llvm/Support/raw_ostream.h"
3899fa1405SMitch Phillips 
3999fa1405SMitch Phillips #include <cstdlib>
4099fa1405SMitch Phillips #include <sstream>
4199fa1405SMitch Phillips 
4299fa1405SMitch Phillips using Instr = ::llvm::cfi_verify::FileAnalysis::Instr;
4399fa1405SMitch Phillips using ::testing::AllOf;
4499fa1405SMitch Phillips using ::testing::Each;
4599fa1405SMitch Phillips using ::testing::ElementsAre;
4699fa1405SMitch Phillips using ::testing::Eq;
4799fa1405SMitch Phillips using ::testing::Field;
4899fa1405SMitch Phillips using ::testing::IsEmpty;
4999fa1405SMitch Phillips using ::testing::Matches;
5099fa1405SMitch Phillips using ::testing::Pair;
5199fa1405SMitch Phillips using ::testing::PrintToString;
5299fa1405SMitch Phillips using ::testing::SizeIs;
5399fa1405SMitch Phillips using ::testing::UnorderedElementsAre;
5499fa1405SMitch Phillips 
5599fa1405SMitch Phillips namespace llvm {
5699fa1405SMitch Phillips namespace cfi_verify {
5799fa1405SMitch Phillips // Printing helpers for gtest.
HexStringifyContainer(const std::vector<uint64_t> & C)5899fa1405SMitch Phillips std::string HexStringifyContainer(const std::vector<uint64_t> &C) {
5999fa1405SMitch Phillips   std::stringstream Stream;
6099fa1405SMitch Phillips   if (C.empty()) {
6199fa1405SMitch Phillips     return "{ }";
6299fa1405SMitch Phillips   }
6399fa1405SMitch Phillips 
6499fa1405SMitch Phillips   Stream << "{ ";
6599fa1405SMitch Phillips   const auto &LastElemIt = std::end(C) - 1;
6699fa1405SMitch Phillips 
6799fa1405SMitch Phillips   for (auto It = std::begin(C); It != LastElemIt; ++It) {
6899fa1405SMitch Phillips     Stream << "0x" << std::hex << *It << ", ";
6999fa1405SMitch Phillips   }
7099fa1405SMitch Phillips   Stream << "0x" << std::hex << *LastElemIt << " }";
7199fa1405SMitch Phillips   return Stream.str();
7299fa1405SMitch Phillips }
7399fa1405SMitch Phillips 
PrintTo(const ConditionalBranchNode & BranchNode,::std::ostream * os)7499fa1405SMitch Phillips void PrintTo(const ConditionalBranchNode &BranchNode, ::std::ostream *os) {
7599fa1405SMitch Phillips   *os << "ConditionalBranchNode<Address: 0x" << std::hex << BranchNode.Address
7699fa1405SMitch Phillips       << ", Target: 0x" << BranchNode.Target << ", Fallthrough: 0x"
7799fa1405SMitch Phillips       << BranchNode.Fallthrough
7899fa1405SMitch Phillips       << ", CFIProtection: " << BranchNode.CFIProtection << ">";
7999fa1405SMitch Phillips }
8099fa1405SMitch Phillips 
PrintTo(const GraphResult & Result,::std::ostream * os)8199fa1405SMitch Phillips void PrintTo(const GraphResult &Result, ::std::ostream *os) {
8299fa1405SMitch Phillips   *os << "Result BaseAddress: 0x" << std::hex << Result.BaseAddress << "\n";
8399fa1405SMitch Phillips 
8499fa1405SMitch Phillips   if (Result.ConditionalBranchNodes.empty())
8599fa1405SMitch Phillips     *os << "  (No conditional branch nodes)\n";
8699fa1405SMitch Phillips 
8799fa1405SMitch Phillips   for (const auto &Node : Result.ConditionalBranchNodes) {
8899fa1405SMitch Phillips     *os << "  ";
8999fa1405SMitch Phillips     PrintTo(Node, os);
9099fa1405SMitch Phillips     *os << "\n    Fallthrough Path: " << std::hex
9199fa1405SMitch Phillips         << HexStringifyContainer(Result.flattenAddress(Node.Fallthrough))
9299fa1405SMitch Phillips         << "\n";
9399fa1405SMitch Phillips     *os << "    Target Path: " << std::hex
9499fa1405SMitch Phillips         << HexStringifyContainer(Result.flattenAddress(Node.Target)) << "\n";
9599fa1405SMitch Phillips   }
9699fa1405SMitch Phillips 
9799fa1405SMitch Phillips   if (Result.OrphanedNodes.empty())
9899fa1405SMitch Phillips     *os << "  (No orphaned nodes)";
9999fa1405SMitch Phillips 
10099fa1405SMitch Phillips   for (const auto &Orphan : Result.OrphanedNodes) {
10199fa1405SMitch Phillips     *os << "  Orphan (0x" << std::hex << Orphan
10299fa1405SMitch Phillips         << ") Path: " << HexStringifyContainer(Result.flattenAddress(Orphan))
10399fa1405SMitch Phillips         << "\n";
10499fa1405SMitch Phillips   }
10599fa1405SMitch Phillips }
10699fa1405SMitch Phillips 
10799fa1405SMitch Phillips namespace {
10899fa1405SMitch Phillips class ELFx86TestFileAnalysis : public FileAnalysis {
10999fa1405SMitch Phillips public:
ELFx86TestFileAnalysis()11099fa1405SMitch Phillips   ELFx86TestFileAnalysis()
11199fa1405SMitch Phillips       : FileAnalysis(Triple("x86_64--"), SubtargetFeatures()) {}
11299fa1405SMitch Phillips 
11399fa1405SMitch Phillips   // Expose this method publicly for testing.
parseSectionContents(ArrayRef<uint8_t> SectionBytes,object::SectionedAddress Address)11499fa1405SMitch Phillips   void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
11577fc1f60SAlexey Lapshin                             object::SectionedAddress Address) {
11677fc1f60SAlexey Lapshin     FileAnalysis::parseSectionContents(SectionBytes, Address);
11799fa1405SMitch Phillips   }
11899fa1405SMitch Phillips 
initialiseDisassemblyMembers()11999fa1405SMitch Phillips   Error initialiseDisassemblyMembers() {
12099fa1405SMitch Phillips     return FileAnalysis::initialiseDisassemblyMembers();
12199fa1405SMitch Phillips   }
12299fa1405SMitch Phillips };
12399fa1405SMitch Phillips 
12499fa1405SMitch Phillips class BasicGraphBuilderTest : public ::testing::Test {
12599fa1405SMitch Phillips protected:
SetUp()12631eb8349SLogan Smith   void SetUp() override {
127c15bdf55SMitch Phillips     IgnoreDWARFFlag = true;
128d9af383dSMitch Phillips     SuccessfullyInitialised = true;
129d9af383dSMitch Phillips     if (auto Err = Analysis.initialiseDisassemblyMembers()) {
130d9af383dSMitch Phillips       handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) {
131d9af383dSMitch Phillips         SuccessfullyInitialised = false;
132d9af383dSMitch Phillips         outs()
133d9af383dSMitch Phillips             << "Note: CFIVerifyTests are disabled due to lack of x86 support "
134d9af383dSMitch Phillips                "on this build.\n";
135d9af383dSMitch Phillips       });
13699fa1405SMitch Phillips     }
13799fa1405SMitch Phillips   }
13899fa1405SMitch Phillips 
139d9af383dSMitch Phillips   bool SuccessfullyInitialised;
14099fa1405SMitch Phillips   ELFx86TestFileAnalysis Analysis;
14199fa1405SMitch Phillips };
14299fa1405SMitch Phillips 
14399fa1405SMitch Phillips MATCHER_P2(HasPath, Result, Matcher, "has path " + PrintToString(Matcher)) {
14499fa1405SMitch Phillips   const auto &Path = Result.flattenAddress(arg);
14599fa1405SMitch Phillips   *result_listener << "the path is " << PrintToString(Path);
14699fa1405SMitch Phillips   return Matches(Matcher)(Path);
14799fa1405SMitch Phillips }
14899fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphTestSinglePathFallthroughUd2)14999fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestSinglePathFallthroughUd2) {
150d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
151*7fc87159SPaul Robinson     GTEST_SKIP();
15299fa1405SMitch Phillips   Analysis.parseSectionContents(
15399fa1405SMitch Phillips       {
15499fa1405SMitch Phillips           0x75, 0x02, // 0: jne 4 [+2]
15599fa1405SMitch Phillips           0x0f, 0x0b, // 2: ud2
15699fa1405SMitch Phillips           0xff, 0x10, // 4: callq *(%rax)
15799fa1405SMitch Phillips       },
15877fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
15977fc1f60SAlexey Lapshin   const auto Result =
16077fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
16199fa1405SMitch Phillips 
16299fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
16399fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1));
16499fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes,
16599fa1405SMitch Phillips               Each(Field(&ConditionalBranchNode::CFIProtection, Eq(true))));
16699fa1405SMitch Phillips   EXPECT_THAT(
16799fa1405SMitch Phillips       Result.ConditionalBranchNodes,
16899fa1405SMitch Phillips       Contains(AllOf(Field(&ConditionalBranchNode::Address, Eq(0xDEADBEEF)),
16999fa1405SMitch Phillips                      Field(&ConditionalBranchNode::Target,
17099fa1405SMitch Phillips                            HasPath(Result, ElementsAre(0xDEADBEEF + 4))),
17199fa1405SMitch Phillips                      Field(&ConditionalBranchNode::Fallthrough,
17299fa1405SMitch Phillips                            HasPath(Result, ElementsAre(0xDEADBEEF + 2))))))
17399fa1405SMitch Phillips       << PrintToString(Result);
17499fa1405SMitch Phillips }
17599fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphTestSinglePathJumpUd2)17699fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestSinglePathJumpUd2) {
177d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
178*7fc87159SPaul Robinson     GTEST_SKIP();
17999fa1405SMitch Phillips   Analysis.parseSectionContents(
18099fa1405SMitch Phillips       {
18199fa1405SMitch Phillips           0x75, 0x02, // 0: jne 4 [+2]
18299fa1405SMitch Phillips           0xff, 0x10, // 2: callq *(%rax)
18399fa1405SMitch Phillips           0x0f, 0x0b, // 4: ud2
18499fa1405SMitch Phillips       },
18577fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
18677fc1f60SAlexey Lapshin   const auto Result =
18777fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
18899fa1405SMitch Phillips 
18999fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
19099fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1));
19199fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes,
19299fa1405SMitch Phillips               Each(Field(&ConditionalBranchNode::CFIProtection, Eq(true))));
19399fa1405SMitch Phillips   EXPECT_THAT(
19499fa1405SMitch Phillips       Result.ConditionalBranchNodes,
19599fa1405SMitch Phillips       Contains(AllOf(Field(&ConditionalBranchNode::Address, Eq(0xDEADBEEF)),
19699fa1405SMitch Phillips                      Field(&ConditionalBranchNode::Target,
19799fa1405SMitch Phillips                            HasPath(Result, ElementsAre(0xDEADBEEF + 4))),
19899fa1405SMitch Phillips                      Field(&ConditionalBranchNode::Fallthrough,
19999fa1405SMitch Phillips                            HasPath(Result, ElementsAre(0xDEADBEEF + 2))))))
20099fa1405SMitch Phillips       << PrintToString(Result);
20199fa1405SMitch Phillips }
20299fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphTestDualPathDualUd2)20399fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestDualPathDualUd2) {
204d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
205*7fc87159SPaul Robinson     GTEST_SKIP();
20699fa1405SMitch Phillips   Analysis.parseSectionContents(
20799fa1405SMitch Phillips       {
20899fa1405SMitch Phillips           0x75, 0x03, // 0: jne 5 [+3]
20999fa1405SMitch Phillips           0x90,       // 2: nop
21099fa1405SMitch Phillips           0xff, 0x10, // 3: callq *(%rax)
21199fa1405SMitch Phillips           0x0f, 0x0b, // 5: ud2
21299fa1405SMitch Phillips           0x75, 0xf9, // 7: jne 2 [-7]
21399fa1405SMitch Phillips           0x0f, 0x0b, // 9: ud2
21499fa1405SMitch Phillips       },
21577fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
21677fc1f60SAlexey Lapshin   const auto Result =
21777fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
21899fa1405SMitch Phillips 
21999fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
22099fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2));
22199fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes,
22299fa1405SMitch Phillips               Each(Field(&ConditionalBranchNode::CFIProtection, Eq(true))));
22399fa1405SMitch Phillips   EXPECT_THAT(
22499fa1405SMitch Phillips       Result.ConditionalBranchNodes,
22599fa1405SMitch Phillips       Contains(AllOf(
22699fa1405SMitch Phillips           Field(&ConditionalBranchNode::Address, Eq(0xDEADBEEF)),
22799fa1405SMitch Phillips           Field(&ConditionalBranchNode::Fallthrough,
22899fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 2, 0xDEADBEEF + 3))),
22999fa1405SMitch Phillips           Field(&ConditionalBranchNode::Target,
23099fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 5))))))
23199fa1405SMitch Phillips       << PrintToString(Result);
23299fa1405SMitch Phillips   EXPECT_THAT(
23399fa1405SMitch Phillips       Result.ConditionalBranchNodes,
23499fa1405SMitch Phillips       Contains(AllOf(
23599fa1405SMitch Phillips           Field(&ConditionalBranchNode::Address, Eq(0xDEADBEEF + 7)),
23699fa1405SMitch Phillips           Field(&ConditionalBranchNode::Fallthrough,
23799fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 9))),
23899fa1405SMitch Phillips           Field(&ConditionalBranchNode::Target,
23999fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 2, 0xDEADBEEF + 3))))))
24099fa1405SMitch Phillips       << PrintToString(Result);
24199fa1405SMitch Phillips }
24299fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphTestDualPathSingleUd2)24399fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestDualPathSingleUd2) {
244d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
245*7fc87159SPaul Robinson     GTEST_SKIP();
24699fa1405SMitch Phillips   Analysis.parseSectionContents(
24799fa1405SMitch Phillips       {
24899fa1405SMitch Phillips           0x75, 0x05, // 0: jne 7 [+5]
24999fa1405SMitch Phillips           0x90,       // 2: nop
25099fa1405SMitch Phillips           0xff, 0x10, // 3: callq *(%rax)
25199fa1405SMitch Phillips           0x75, 0xfb, // 5: jne 2 [-5]
25299fa1405SMitch Phillips           0x0f, 0x0b, // 7: ud2
25399fa1405SMitch Phillips       },
25477fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
25577fc1f60SAlexey Lapshin   GraphResult Result =
25677fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
25799fa1405SMitch Phillips 
25899fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
25999fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2));
26099fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes,
26199fa1405SMitch Phillips               Each(Field(&ConditionalBranchNode::CFIProtection, Eq(true))));
26299fa1405SMitch Phillips   EXPECT_THAT(
26399fa1405SMitch Phillips       Result.ConditionalBranchNodes,
26499fa1405SMitch Phillips       Contains(AllOf(
26599fa1405SMitch Phillips           Field(&ConditionalBranchNode::Address, Eq(0xDEADBEEF)),
26699fa1405SMitch Phillips           Field(&ConditionalBranchNode::Fallthrough,
26799fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 2, 0xDEADBEEF + 3))),
26899fa1405SMitch Phillips           Field(&ConditionalBranchNode::Target,
26999fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 7))))))
27099fa1405SMitch Phillips       << PrintToString(Result);
27199fa1405SMitch Phillips   EXPECT_THAT(
27299fa1405SMitch Phillips       Result.ConditionalBranchNodes,
27399fa1405SMitch Phillips       Contains(AllOf(
27499fa1405SMitch Phillips           Field(&ConditionalBranchNode::Address, Eq(0xDEADBEEF + 5)),
27599fa1405SMitch Phillips           Field(&ConditionalBranchNode::Fallthrough,
27699fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 7))),
27799fa1405SMitch Phillips           Field(&ConditionalBranchNode::Target,
27899fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 2, 0xDEADBEEF + 3))))))
27999fa1405SMitch Phillips       << PrintToString(Result);
28099fa1405SMitch Phillips }
28199fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphFailures)28299fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphFailures) {
283d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
284*7fc87159SPaul Robinson     GTEST_SKIP();
28599fa1405SMitch Phillips   Analysis.parseSectionContents(
28699fa1405SMitch Phillips       {
28799fa1405SMitch Phillips           0x90,       // 0: nop
28899fa1405SMitch Phillips           0x75, 0xfe, // 1: jne 1 [-2]
28999fa1405SMitch Phillips       },
29077fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
29177fc1f60SAlexey Lapshin   GraphResult Result =
29277fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0});
29399fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
29499fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
29599fa1405SMitch Phillips 
29677fc1f60SAlexey Lapshin   Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 1, 0x0});
29799fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
29899fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
29999fa1405SMitch Phillips 
30077fc1f60SAlexey Lapshin   Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADC0DE, 0x0});
30199fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
30299fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
30399fa1405SMitch Phillips }
30499fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphNoXrefs)30599fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphNoXrefs) {
306d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
307*7fc87159SPaul Robinson     GTEST_SKIP();
30899fa1405SMitch Phillips   Analysis.parseSectionContents(
30999fa1405SMitch Phillips       {
31099fa1405SMitch Phillips           0xeb, 0xfe, // 0: jmp 0 [-2]
31199fa1405SMitch Phillips           0xff, 0x10, // 2: callq *(%rax)
31299fa1405SMitch Phillips       },
31377fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
31477fc1f60SAlexey Lapshin   GraphResult Result =
31577fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
31699fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
31799fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, ElementsAre(0xDEADBEEF + 2));
31899fa1405SMitch Phillips   EXPECT_THAT(Result.IntermediateNodes, IsEmpty());
31999fa1405SMitch Phillips }
32099fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphConditionalInfiniteLoop)32199fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphConditionalInfiniteLoop) {
322d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
323*7fc87159SPaul Robinson     GTEST_SKIP();
32499fa1405SMitch Phillips   Analysis.parseSectionContents(
32599fa1405SMitch Phillips       {
32699fa1405SMitch Phillips           0x75, 0xfe, // 0: jne 0 [-2]
32799fa1405SMitch Phillips           0xff, 0x10, // 2: callq *(%rax)
32899fa1405SMitch Phillips       },
32977fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
33077fc1f60SAlexey Lapshin   GraphResult Result =
33177fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
33299fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
33399fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1));
33499fa1405SMitch Phillips   EXPECT_THAT(
33599fa1405SMitch Phillips       Result.ConditionalBranchNodes,
33699fa1405SMitch Phillips       Each(AllOf(Field(&ConditionalBranchNode::CFIProtection, Eq(false)),
33799fa1405SMitch Phillips                  Field(&ConditionalBranchNode::Target,
33899fa1405SMitch Phillips                        HasPath(Result, ElementsAre(0xDEADBEEF))),
33999fa1405SMitch Phillips                  Field(&ConditionalBranchNode::Fallthrough,
34099fa1405SMitch Phillips                        HasPath(Result, ElementsAre(0xDEADBEEF + 2))))))
34199fa1405SMitch Phillips       << PrintToString(Result);
34299fa1405SMitch Phillips }
34399fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphUnconditionalInfiniteLoop)34499fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphUnconditionalInfiniteLoop) {
345d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
346*7fc87159SPaul Robinson     GTEST_SKIP();
34799fa1405SMitch Phillips   Analysis.parseSectionContents(
34899fa1405SMitch Phillips       {
34999fa1405SMitch Phillips           0x75, 0x02, // 0: jne 4 [+2]
35099fa1405SMitch Phillips           0xeb, 0xfc, // 2: jmp 0 [-4]
35199fa1405SMitch Phillips           0xff, 0x10, // 4: callq *(%rax)
35299fa1405SMitch Phillips       },
35377fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
35477fc1f60SAlexey Lapshin   GraphResult Result =
35577fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
35699fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
35799fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(1));
35899fa1405SMitch Phillips   EXPECT_THAT(
35999fa1405SMitch Phillips       Result.ConditionalBranchNodes,
36099fa1405SMitch Phillips       Contains(
36199fa1405SMitch Phillips           AllOf(Field(&ConditionalBranchNode::Address, Eq(0xDEADBEEF)),
36299fa1405SMitch Phillips                 Field(&ConditionalBranchNode::Fallthrough,
36399fa1405SMitch Phillips                       HasPath(Result, ElementsAre(0xDEADBEEF + 2, 0xDEADBEEF))),
36499fa1405SMitch Phillips                 Field(&ConditionalBranchNode::Target,
36599fa1405SMitch Phillips                       HasPath(Result, ElementsAre(0xDEADBEEF + 4))))))
36699fa1405SMitch Phillips       << PrintToString(Result);
36799fa1405SMitch Phillips }
36899fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphNoFlowsToIndirection)36999fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphNoFlowsToIndirection) {
370d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
371*7fc87159SPaul Robinson     GTEST_SKIP();
37299fa1405SMitch Phillips   Analysis.parseSectionContents(
37399fa1405SMitch Phillips       {
37499fa1405SMitch Phillips           0x75, 0x00, // 0: jne 2 [+0]
37599fa1405SMitch Phillips           0xeb, 0xfc, // 2: jmp 0 [-4]
37699fa1405SMitch Phillips           0xff, 0x10, // 4: callq *(%rax)
37799fa1405SMitch Phillips       },
37877fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
37977fc1f60SAlexey Lapshin   GraphResult Result =
38077fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0});
38199fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, ElementsAre(0xDEADBEEF + 4));
38299fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
38399fa1405SMitch Phillips }
38499fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphLengthExceededUpwards)38599fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphLengthExceededUpwards) {
386d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
387*7fc87159SPaul Robinson     GTEST_SKIP();
38899fa1405SMitch Phillips   Analysis.parseSectionContents(
38999fa1405SMitch Phillips       {
39099fa1405SMitch Phillips           0x75, 0x06, // 0: jne 8 [+6]
39199fa1405SMitch Phillips           0x90,       // 2: nop
39299fa1405SMitch Phillips           0x90,       // 3: nop
39399fa1405SMitch Phillips           0x90,       // 4: nop
39499fa1405SMitch Phillips           0x90,       // 5: nop
39599fa1405SMitch Phillips           0xff, 0x10, // 6: callq *(%rax)
39699fa1405SMitch Phillips           0x0f, 0x0b, // 8: ud2
39799fa1405SMitch Phillips       },
39877fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
39999fa1405SMitch Phillips   uint64_t PrevSearchLengthForConditionalBranch =
40099fa1405SMitch Phillips       SearchLengthForConditionalBranch;
40199fa1405SMitch Phillips   SearchLengthForConditionalBranch = 2;
40299fa1405SMitch Phillips 
40377fc1f60SAlexey Lapshin   GraphResult Result =
40477fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 6, 0x0});
40599fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, SizeIs(1));
40699fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes,
40799fa1405SMitch Phillips               Each(HasPath(Result, ElementsAre(0xDEADBEEF + 4, 0xDEADBEEF + 5,
40899fa1405SMitch Phillips                                                0xDEADBEEF + 6))))
40999fa1405SMitch Phillips       << PrintToString(Result);
41099fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, IsEmpty());
41199fa1405SMitch Phillips 
41299fa1405SMitch Phillips   SearchLengthForConditionalBranch = PrevSearchLengthForConditionalBranch;
41399fa1405SMitch Phillips }
41499fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphLengthExceededDownwards)41599fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphLengthExceededDownwards) {
416d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
417*7fc87159SPaul Robinson     GTEST_SKIP();
41899fa1405SMitch Phillips   Analysis.parseSectionContents(
41999fa1405SMitch Phillips       {
42099fa1405SMitch Phillips           0x75, 0x02, // 0: jne 4 [+2]
42199fa1405SMitch Phillips           0xff, 0x10, // 2: callq *(%rax)
42299fa1405SMitch Phillips           0x90,       // 4: nop
42399fa1405SMitch Phillips           0x90,       // 5: nop
42499fa1405SMitch Phillips           0x90,       // 6: nop
42599fa1405SMitch Phillips           0x90,       // 7: nop
42699fa1405SMitch Phillips           0x0f, 0x0b, // 8: ud2
42799fa1405SMitch Phillips       },
42877fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
42999fa1405SMitch Phillips   uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
43099fa1405SMitch Phillips   SearchLengthForUndef = 2;
43199fa1405SMitch Phillips 
43277fc1f60SAlexey Lapshin   GraphResult Result =
43377fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0});
43499fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
43599fa1405SMitch Phillips   EXPECT_THAT(
43699fa1405SMitch Phillips       Result.ConditionalBranchNodes,
43799fa1405SMitch Phillips       Each(AllOf(
43899fa1405SMitch Phillips           Field(&ConditionalBranchNode::CFIProtection, Eq(false)),
43999fa1405SMitch Phillips           Field(&ConditionalBranchNode::Address, Eq(0xDEADBEEF)),
44099fa1405SMitch Phillips           Field(&ConditionalBranchNode::Target,
44199fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 4, 0xDEADBEEF + 5))),
44299fa1405SMitch Phillips           Field(&ConditionalBranchNode::Fallthrough,
44399fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 2))))))
44499fa1405SMitch Phillips       << PrintToString(Result);
44599fa1405SMitch Phillips 
44699fa1405SMitch Phillips   SearchLengthForUndef = PrevSearchLengthForUndef;
44799fa1405SMitch Phillips }
44899fa1405SMitch Phillips 
44999fa1405SMitch Phillips // This test ensures when avoiding doing repeated work we still generate the
45099fa1405SMitch Phillips // paths correctly. We don't need to recalculate the flow from 0x2 -> 0x3 as it
45199fa1405SMitch Phillips // should only need to be generated once.
TEST_F(BasicGraphBuilderTest,BuildFlowGraphWithRepeatedWork)45299fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphWithRepeatedWork) {
453d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
454*7fc87159SPaul Robinson     GTEST_SKIP();
45599fa1405SMitch Phillips   Analysis.parseSectionContents(
45699fa1405SMitch Phillips       {
45799fa1405SMitch Phillips           0x75, 0x05, // 0: jne 7 [+5]
45899fa1405SMitch Phillips           0x90,       // 2: nop
45999fa1405SMitch Phillips           0xff, 0x10, // 3: callq *(%rax)
46099fa1405SMitch Phillips           0x75, 0xfb, // 5: jne 2 [-5]
46199fa1405SMitch Phillips           0x0f, 0x0b, // 7: ud2
46299fa1405SMitch Phillips       },
46377fc1f60SAlexey Lapshin       {0xDEADBEEF, 0x0});
46477fc1f60SAlexey Lapshin   GraphResult Result =
46577fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0});
46699fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, IsEmpty());
46799fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(2));
46899fa1405SMitch Phillips   EXPECT_THAT(
46999fa1405SMitch Phillips       Result.ConditionalBranchNodes,
47099fa1405SMitch Phillips       Contains(AllOf(
47199fa1405SMitch Phillips           Field(&ConditionalBranchNode::CFIProtection, Eq(true)),
47299fa1405SMitch Phillips           Field(&ConditionalBranchNode::Address, Eq(0xDEADBEEF)),
47399fa1405SMitch Phillips           Field(&ConditionalBranchNode::Target,
47499fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 7))),
47599fa1405SMitch Phillips           Field(&ConditionalBranchNode::Fallthrough,
47699fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 2, 0xDEADBEEF + 3))))))
47799fa1405SMitch Phillips       << PrintToString(Result);
47899fa1405SMitch Phillips   EXPECT_THAT(
47999fa1405SMitch Phillips       Result.ConditionalBranchNodes,
48099fa1405SMitch Phillips       Contains(AllOf(
48199fa1405SMitch Phillips           Field(&ConditionalBranchNode::CFIProtection, Eq(true)),
48299fa1405SMitch Phillips           Field(&ConditionalBranchNode::Address, Eq(0xDEADBEEF + 5)),
48399fa1405SMitch Phillips           Field(&ConditionalBranchNode::Target,
48499fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 2, 0xDEADBEEF + 3))),
48599fa1405SMitch Phillips           Field(&ConditionalBranchNode::Fallthrough,
48699fa1405SMitch Phillips                 HasPath(Result, ElementsAre(0xDEADBEEF + 7))))))
48799fa1405SMitch Phillips       << PrintToString(Result);
48899fa1405SMitch Phillips   EXPECT_THAT(Result.IntermediateNodes, SizeIs(1));
48999fa1405SMitch Phillips   EXPECT_THAT(Result.IntermediateNodes,
49099fa1405SMitch Phillips               UnorderedElementsAre(Pair(0xDEADBEEF + 2, 0xDEADBEEF + 3)));
49199fa1405SMitch Phillips }
49299fa1405SMitch Phillips 
TEST_F(BasicGraphBuilderTest,BuildFlowGraphComplexExample)49399fa1405SMitch Phillips TEST_F(BasicGraphBuilderTest, BuildFlowGraphComplexExample) {
494d9af383dSMitch Phillips   if (!SuccessfullyInitialised)
495*7fc87159SPaul Robinson     GTEST_SKIP();
49699fa1405SMitch Phillips   // The following code has this graph:
49799fa1405SMitch Phillips   //  +----------+      +--------------+
49899fa1405SMitch Phillips   //  |    20    | <--- |      0       |
49999fa1405SMitch Phillips   //  +----------+      +--------------+
50099fa1405SMitch Phillips   //    |                 |
50199fa1405SMitch Phillips   //    v                 v
50299fa1405SMitch Phillips   //  +----------+      +--------------+
50399fa1405SMitch Phillips   //  |    21    |      |      2       |
50499fa1405SMitch Phillips   //  +----------+      +--------------+
50599fa1405SMitch Phillips   //    |                 |
50699fa1405SMitch Phillips   //    v                 v
50799fa1405SMitch Phillips   //  +----------+      +--------------+
50899fa1405SMitch Phillips   //  | 22 (ud2) |  +-> |      7       |
50999fa1405SMitch Phillips   //  +----------+  |   +--------------+
51099fa1405SMitch Phillips   //    ^           |     |
51199fa1405SMitch Phillips   //    |           |     v
51299fa1405SMitch Phillips   //  +----------+  |   +--------------+
51399fa1405SMitch Phillips   //  |    4     |  |   |      8       |
51499fa1405SMitch Phillips   //  +----------+  |   +--------------+
51599fa1405SMitch Phillips   //    |           |     |
51699fa1405SMitch Phillips   //    v           |     v
51799fa1405SMitch Phillips   //  +----------+  |   +--------------+    +------------+
51899fa1405SMitch Phillips   //  |    6     | -+   | 9 (indirect) | <- |     13     |
51999fa1405SMitch Phillips   //  +----------+      +--------------+    +------------+
52099fa1405SMitch Phillips   //                      ^                   |
52199fa1405SMitch Phillips   //                      |                   v
52299fa1405SMitch Phillips   //                    +--------------+    +------------+
52399fa1405SMitch Phillips   //                    |      11      |    | 15 (error) |
52499fa1405SMitch Phillips   //                    +--------------+    +------------+
52599fa1405SMitch Phillips   // Or, in image format: https://i.imgur.com/aX5fCoi.png
52699fa1405SMitch Phillips 
52799fa1405SMitch Phillips   Analysis.parseSectionContents(
52899fa1405SMitch Phillips       {
52999fa1405SMitch Phillips           0x75, 0x12,                   // 0: jne 20 [+18]
53099fa1405SMitch Phillips           0xeb, 0x03,                   // 2: jmp 7 [+3]
53199fa1405SMitch Phillips           0x75, 0x10,                   // 4: jne 22 [+16]
53299fa1405SMitch Phillips           0x90,                         // 6: nop
53399fa1405SMitch Phillips           0x90,                         // 7: nop
53499fa1405SMitch Phillips           0x90,                         // 8: nop
53599fa1405SMitch Phillips           0xff, 0x10,                   // 9: callq *(%rax)
53699fa1405SMitch Phillips           0xeb, 0xfc,                   // 11: jmp 9 [-4]
53799fa1405SMitch Phillips           0x75, 0xfa,                   // 13: jne 9 [-6]
53899fa1405SMitch Phillips           0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678]
53999fa1405SMitch Phillips           0x90,                         // 20: nop
54099fa1405SMitch Phillips           0x90,                         // 21: nop
54199fa1405SMitch Phillips           0x0f, 0x0b,                   // 22: ud2
54299fa1405SMitch Phillips       },
54377fc1f60SAlexey Lapshin       {0x1000, 0x0});
54499fa1405SMitch Phillips   uint64_t PrevSearchLengthForUndef = SearchLengthForUndef;
54599fa1405SMitch Phillips   SearchLengthForUndef = 5;
54699fa1405SMitch Phillips 
54777fc1f60SAlexey Lapshin   GraphResult Result =
54877fc1f60SAlexey Lapshin       GraphBuilder::buildFlowGraph(Analysis, {0x1000 + 9, 0x0});
54999fa1405SMitch Phillips 
55099fa1405SMitch Phillips   EXPECT_THAT(Result.OrphanedNodes, SizeIs(1));
55199fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes, SizeIs(3));
55299fa1405SMitch Phillips 
55399fa1405SMitch Phillips   EXPECT_THAT(
55499fa1405SMitch Phillips       Result.OrphanedNodes,
55599fa1405SMitch Phillips       Each(AllOf(Eq(0x1000u + 11),
55699fa1405SMitch Phillips                  HasPath(Result, ElementsAre(0x1000 + 11, 0x1000 + 9)))))
55799fa1405SMitch Phillips       << PrintToString(Result);
55899fa1405SMitch Phillips 
55999fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes,
56099fa1405SMitch Phillips               Contains(AllOf(
56199fa1405SMitch Phillips                   Field(&ConditionalBranchNode::CFIProtection, Eq(true)),
56299fa1405SMitch Phillips                   Field(&ConditionalBranchNode::Address, Eq(0x1000u)),
56399fa1405SMitch Phillips                   Field(&ConditionalBranchNode::Target,
56499fa1405SMitch Phillips                         HasPath(Result, ElementsAre(0x1000 + 20, 0x1000 + 21,
56599fa1405SMitch Phillips                                                     0x1000 + 22))),
56699fa1405SMitch Phillips                   Field(&ConditionalBranchNode::Fallthrough,
56799fa1405SMitch Phillips                         HasPath(Result, ElementsAre(0x1000 + 2, 0x1000 + 7,
56899fa1405SMitch Phillips                                                     0x1000 + 8, 0x1000 + 9))))))
56999fa1405SMitch Phillips       << PrintToString(Result);
57099fa1405SMitch Phillips 
57199fa1405SMitch Phillips   EXPECT_THAT(Result.ConditionalBranchNodes,
57299fa1405SMitch Phillips               Contains(AllOf(
57399fa1405SMitch Phillips                   Field(&ConditionalBranchNode::CFIProtection, Eq(true)),
57499fa1405SMitch Phillips                   Field(&ConditionalBranchNode::Address, Eq(0x1000u + 4)),
57599fa1405SMitch Phillips                   Field(&ConditionalBranchNode::Target,
57699fa1405SMitch Phillips                         HasPath(Result, ElementsAre(0x1000 + 22))),
57799fa1405SMitch Phillips                   Field(&ConditionalBranchNode::Fallthrough,
57899fa1405SMitch Phillips                         HasPath(Result, ElementsAre(0x1000 + 6, 0x1000 + 7,
57999fa1405SMitch Phillips                                                     0x1000 + 8, 0x1000 + 9))))))
58099fa1405SMitch Phillips       << PrintToString(Result);
58199fa1405SMitch Phillips 
58299fa1405SMitch Phillips   EXPECT_THAT(
58399fa1405SMitch Phillips       Result.ConditionalBranchNodes,
58499fa1405SMitch Phillips       Contains(AllOf(Field(&ConditionalBranchNode::CFIProtection, Eq(false)),
58599fa1405SMitch Phillips                      Field(&ConditionalBranchNode::Address, Eq(0x1000u + 13)),
58699fa1405SMitch Phillips                      Field(&ConditionalBranchNode::Target,
58799fa1405SMitch Phillips                            HasPath(Result, ElementsAre(0x1000 + 9))),
58899fa1405SMitch Phillips                      Field(&ConditionalBranchNode::Fallthrough,
58999fa1405SMitch Phillips                            HasPath(Result, ElementsAre(0x1000 + 15))))))
59099fa1405SMitch Phillips       << PrintToString(Result);
59199fa1405SMitch Phillips 
59299fa1405SMitch Phillips   SearchLengthForUndef = PrevSearchLengthForUndef;
59399fa1405SMitch Phillips }
59499fa1405SMitch Phillips 
59599fa1405SMitch Phillips } // anonymous namespace
59699fa1405SMitch Phillips } // end namespace cfi_verify
59799fa1405SMitch Phillips } // end namespace llvm
598