#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
dwarf::CIE createCIE(bool IsDWARF64, uint64_t Offset, uint64_t Length) {
  return dwarf::CIE(IsDWARF64, Offset, Length,
                    3,
                    StringRef(),
                    8,
                    0,
                    1,
                    -8,
                    16,
                    StringRef(),
                    dwarf::DW_EH_PE_absptr,
                    dwarf::DW_EH_PE_omit,
                    None,
                    None,
                    Triple::x86_64);
}
void expectDumpResult(const dwarf::CIE &TestCIE, bool IsEH,
                      StringRef ExpectedFirstLine) {
  std::string Output;
  raw_string_ostream OS(Output);
  TestCIE.dump(OS, DIDumpOptions(), nullptr, IsEH);
  OS.flush();
  StringRef FirstLine = StringRef(Output).split('\n').first;
  EXPECT_EQ(FirstLine, ExpectedFirstLine);
}
void expectDumpResult(const dwarf::FDE &TestFDE, bool IsEH,
                      StringRef ExpectedFirstLine) {
  std::string Output;
  raw_string_ostream OS(Output);
  TestFDE.dump(OS, DIDumpOptions(), nullptr, IsEH);
  OS.flush();
  StringRef FirstLine = StringRef(Output).split('\n').first;
  EXPECT_EQ(FirstLine, ExpectedFirstLine);
}
TEST(DWARFDebugFrame, DumpDWARF32CIE) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x1111abcd,
                                 0x2222abcd);
  expectDumpResult(TestCIE, false, "1111abcd 2222abcd ffffffff CIE");
}
TEST(DWARFDebugFrame, DumpDWARF64CIE) {
  dwarf::CIE TestCIE = createCIE(true,
                                 0x1111abcdabcd,
                                 0x2222abcdabcd);
  expectDumpResult(TestCIE, false,
                   "1111abcdabcd 00002222abcdabcd ffffffffffffffff CIE");
}
TEST(DWARFDebugFrame, DumpEHCIE) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x1000,
                                 0x20);
  expectDumpResult(TestCIE, true, "00001000 00000020 00000000 CIE");
}
TEST(DWARFDebugFrame, DumpEH64CIE) {
  dwarf::CIE TestCIE = createCIE(true,
                                 0x1000,
                                 0x20);
  expectDumpResult(TestCIE, true,
                   "00001000 0000000000000020 00000000 CIE");
}
TEST(DWARFDebugFrame, DumpDWARF64FDE) {
  dwarf::CIE TestCIE = createCIE(true,
                                 0x1111abcdabcd,
                                 0x2222abcdabcd);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x5555abcdabcd,
                     0x111111111111,
                     &TestCIE,
                     None,
                     Triple::x86_64);
  expectDumpResult(TestFDE, false,
                   "3333abcdabcd 00004444abcdabcd 00001111abcdabcd FDE "
                   "cie=1111abcdabcd pc=5555abcdabcd...6666bcdebcde");
}
TEST(DWARFDebugFrame, DumpEH64FDE) {
  dwarf::CIE TestCIE = createCIE(true,
                                 0x1111ab9a000c,
                                 0x20);
  dwarf::FDE TestFDE(true,
                     0x1111abcdabcd,
                     0x2222abcdabcd,
                     0x33abcd,
                     0x4444abcdabcd,
                     0x111111111111,
                     &TestCIE,
                     None,
                     Triple::x86_64);
  expectDumpResult(TestFDE, true,
                   "1111abcdabcd 00002222abcdabcd 0033abcd FDE "
                   "cie=1111ab9a000c pc=4444abcdabcd...5555bcdebcde");
}
static Error parseCFI(dwarf::CIE &C, ArrayRef<uint8_t> Instructions,
                      Optional<uint64_t> Size = None) {
  DWARFDataExtractor Data(Instructions, true,
                          8);
  uint64_t Offset = 0;
  const uint64_t EndOffset = Size ? *Size : (uint64_t)Instructions.size();
  return C.cfis().parse(Data, &Offset, EndOffset);
}
static Error parseCFI(dwarf::FDE &FDE, ArrayRef<uint8_t> Instructions) {
  DWARFDataExtractor Data(Instructions, true,
                          8);
  uint64_t Offset = 0;
  return FDE.cfis().parse(Data, &Offset, Instructions.size());
}
TEST(DWARFDebugFrame, InvalidCFIOpcodesTest) {
  llvm::DenseSet<uint8_t> ValidExtendedOpcodes = {
      dwarf::DW_CFA_nop,
      dwarf::DW_CFA_advance_loc,
      dwarf::DW_CFA_offset,
      dwarf::DW_CFA_restore,
      dwarf::DW_CFA_set_loc,
      dwarf::DW_CFA_advance_loc1,
      dwarf::DW_CFA_advance_loc2,
      dwarf::DW_CFA_advance_loc4,
      dwarf::DW_CFA_offset_extended,
      dwarf::DW_CFA_restore_extended,
      dwarf::DW_CFA_undefined,
      dwarf::DW_CFA_same_value,
      dwarf::DW_CFA_register,
      dwarf::DW_CFA_remember_state,
      dwarf::DW_CFA_restore_state,
      dwarf::DW_CFA_def_cfa,
      dwarf::DW_CFA_def_cfa_register,
      dwarf::DW_CFA_def_cfa_offset,
      dwarf::DW_CFA_def_cfa_expression,
      dwarf::DW_CFA_expression,
      dwarf::DW_CFA_offset_extended_sf,
      dwarf::DW_CFA_def_cfa_sf,
      dwarf::DW_CFA_def_cfa_offset_sf,
      dwarf::DW_CFA_LLVM_def_aspace_cfa,
      dwarf::DW_CFA_LLVM_def_aspace_cfa_sf,
      dwarf::DW_CFA_val_offset,
      dwarf::DW_CFA_val_offset_sf,
      dwarf::DW_CFA_val_expression,
      dwarf::DW_CFA_MIPS_advance_loc8,
      dwarf::DW_CFA_GNU_window_save,
      dwarf::DW_CFA_AARCH64_negate_ra_state,
      dwarf::DW_CFA_GNU_args_size};
  dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
      for (uint8_t Code = 0; Code <= 63; ++Code) {
    if (ValidExtendedOpcodes.count(Code))
      continue;
    EXPECT_THAT_ERROR(parseCFI(TestCIE, Code),
                      FailedWithMessage(("invalid extended CFI opcode 0x" +
                                         Twine::utohexstr(Code))
                                            .str()
                                            .c_str()));
  }
}
TEST(DWARFDebugFrame, ParseTruncatedCFITest) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
    EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
      EXPECT_THAT_ERROR(
      parseCFI(TestCIE, {}, 1),
      FailedWithMessage(
          "unexpected end of data at offset 0x0 while reading [0x0, 0x1)"));
    EXPECT_THAT_ERROR(
      parseCFI(TestCIE, {dwarf::DW_CFA_offset}),
      FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
                        "malformed uleb128, extends past end"));
    EXPECT_THAT_ERROR(
      parseCFI(TestCIE, {dwarf::DW_CFA_set_loc}),
      FailedWithMessage(
          "unexpected end of data at offset 0x1 while reading [0x1, 0x9)"));
    EXPECT_THAT_ERROR(
      parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc1}),
      FailedWithMessage(
          "unexpected end of data at offset 0x1 while reading [0x1, 0x2)"));
    EXPECT_THAT_ERROR(
      parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc2}),
      FailedWithMessage(
          "unexpected end of data at offset 0x1 while reading [0x1, 0x3)"));
    EXPECT_THAT_ERROR(
      parseCFI(TestCIE, {dwarf::DW_CFA_advance_loc4}),
      FailedWithMessage(
          "unexpected end of data at offset 0x1 while reading [0x1, 0x5)"));
    auto CheckOp_ULEB128 = [&](uint8_t Inst) {
    EXPECT_THAT_ERROR(
        parseCFI(TestCIE, Inst),
        FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
                          "malformed uleb128, extends past end"));
  };
  for (uint8_t Inst :
       {dwarf::DW_CFA_restore_extended, dwarf::DW_CFA_undefined,
        dwarf::DW_CFA_same_value, dwarf::DW_CFA_def_cfa_register,
        dwarf::DW_CFA_def_cfa_offset, dwarf::DW_CFA_GNU_args_size})
    CheckOp_ULEB128(Inst);
    EXPECT_THAT_ERROR(
      parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_offset_sf}),
      FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
                        "malformed sleb128, extends past end"));
    auto CheckOp_ULEB128_ULEB128 = [&](uint8_t Inst) {
    EXPECT_THAT_ERROR(
        parseCFI(TestCIE, Inst),
        FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
                          "malformed uleb128, extends past end"));
    EXPECT_THAT_ERROR(
        parseCFI(TestCIE, {Inst, 0}),
        FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
                          "malformed uleb128, extends past end"));
  };
  for (uint8_t Inst : {dwarf::DW_CFA_offset_extended, dwarf::DW_CFA_register,
                       dwarf::DW_CFA_def_cfa, dwarf::DW_CFA_LLVM_def_aspace_cfa,
                       dwarf::DW_CFA_val_offset})
    CheckOp_ULEB128_ULEB128(Inst);
    auto CheckOp_ULEB128_SLEB128 = [&](uint8_t Inst) {
    EXPECT_THAT_ERROR(
        parseCFI(TestCIE, Inst),
        FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
                          "malformed uleb128, extends past end"));
    EXPECT_THAT_ERROR(
        parseCFI(TestCIE, {Inst, 0}),
        FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
                          "malformed sleb128, extends past end"));
  };
  for (uint8_t Inst :
       {dwarf::DW_CFA_offset_extended_sf, dwarf::DW_CFA_def_cfa_sf,
        dwarf::DW_CFA_LLVM_def_aspace_cfa_sf, dwarf::DW_CFA_val_offset_sf})
    CheckOp_ULEB128_SLEB128(Inst);
    EXPECT_THAT_ERROR(
      parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression}),
      FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
                        "malformed uleb128, extends past end"));
  EXPECT_THAT_ERROR(
      parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
                         0x1}),
      FailedWithMessage(
          "unexpected end of data at offset 0x2 while reading [0x2, 0x3)"));
    EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_expression,
                                       0}),
                    Succeeded());
      auto CheckOp_ULEB128_Expr = [&](uint8_t Inst) {
    EXPECT_THAT_ERROR(
        parseCFI(TestCIE, {Inst}),
        FailedWithMessage("unable to decode LEB128 at offset 0x00000001: "
                          "malformed uleb128, extends past end"));
    EXPECT_THAT_ERROR(
        parseCFI(TestCIE, {Inst, 0}),
        FailedWithMessage("unable to decode LEB128 at offset 0x00000002: "
                          "malformed uleb128, extends past end"));
        EXPECT_THAT_ERROR(parseCFI(TestCIE, {Inst,
                                         0, 0}),
                      Succeeded());
    EXPECT_THAT_ERROR(
        parseCFI(TestCIE, {Inst,
                           0, 1}),
        FailedWithMessage(
            "unexpected end of data at offset 0x3 while reading [0x3, 0x4)"));
  };
  for (uint8_t Inst : {dwarf::DW_CFA_expression, dwarf::DW_CFA_val_expression})
    CheckOp_ULEB128_Expr(Inst);
}
void expectDumpResult(const dwarf::UnwindLocation &Loc,
                      StringRef ExpectedFirstLine) {
  std::string Output;
  raw_string_ostream OS(Output);
  OS << Loc;
  OS.flush();
  StringRef FirstLine = StringRef(Output).split('\n').first;
  EXPECT_EQ(FirstLine, ExpectedFirstLine);
}
TEST(DWARFDebugFrame, DumpUnwindLocations) {
    constexpr int32_t PlusOff = 8;
  constexpr int32_t MinusOff = -8;
  constexpr uint8_t RegNum = 12;
  expectDumpResult(dwarf::UnwindLocation::createUnspecified(), "unspecified");
  expectDumpResult(dwarf::UnwindLocation::createUndefined(), "undefined");
  expectDumpResult(dwarf::UnwindLocation::createSame(), "same");
  expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(PlusOff),
                   "CFA+8");
  expectDumpResult(dwarf::UnwindLocation::createIsCFAPlusOffset(MinusOff),
                   "CFA-8");
  expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(PlusOff),
                   "[CFA+8]");
  expectDumpResult(dwarf::UnwindLocation::createAtCFAPlusOffset(MinusOff),
                   "[CFA-8]");
  expectDumpResult(
      dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, PlusOff),
      "reg12+8");
  expectDumpResult(
      dwarf::UnwindLocation::createIsRegisterPlusOffset(RegNum, MinusOff),
      "reg12-8");
  expectDumpResult(
      dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, PlusOff),
      "[reg12+8]");
  expectDumpResult(
      dwarf::UnwindLocation::createAtRegisterPlusOffset(RegNum, MinusOff),
      "[reg12-8]");
  expectDumpResult(dwarf::UnwindLocation::createIsConstant(12), "12");
  expectDumpResult(dwarf::UnwindLocation::createIsConstant(-32), "-32");
}
void expectDumpResult(const dwarf::RegisterLocations &Locs,
                      StringRef ExpectedFirstLine) {
  std::string Output;
  raw_string_ostream OS(Output);
  OS << Locs;
  OS.flush();
  StringRef FirstLine = StringRef(Output).split('\n').first;
  EXPECT_EQ(FirstLine, ExpectedFirstLine);
}
TEST(DWARFDebugFrame, RegisterLocations) {
    dwarf::RegisterLocations Locs;
  expectDumpResult(Locs, "");
  EXPECT_FALSE(Locs.hasLocations());
      Locs.setRegisterLocation(12, dwarf::UnwindLocation::createUnspecified());
  EXPECT_TRUE(Locs.hasLocations());
  expectDumpResult(Locs, "reg12=unspecified");
      Locs.setRegisterLocation(12, dwarf::UnwindLocation::createSame());
  EXPECT_TRUE(Locs.hasLocations());
  expectDumpResult(Locs, "reg12=same");
      Locs.removeRegisterLocation(12);
  EXPECT_FALSE(Locs.hasLocations());
  expectDumpResult(Locs, "");
    auto Reg12Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(4);
  auto Reg13Loc = dwarf::UnwindLocation::createAtCFAPlusOffset(8);
  auto Reg14Loc = dwarf::UnwindLocation::createSame();
  Locs.setRegisterLocation(12, Reg12Loc);
  Locs.setRegisterLocation(13, Reg13Loc);
  Locs.setRegisterLocation(14, Reg14Loc);
  EXPECT_TRUE(Locs.hasLocations());
  expectDumpResult(Locs, "reg12=[CFA+4], reg13=[CFA+8], reg14=same");
    Optional<dwarf::UnwindLocation> OptionalLoc;
  OptionalLoc = Locs.getRegisterLocation(0);
  EXPECT_FALSE(OptionalLoc.has_value());
  OptionalLoc = Locs.getRegisterLocation(12);
  EXPECT_TRUE(OptionalLoc.has_value());
  EXPECT_EQ(*OptionalLoc, Reg12Loc);
  OptionalLoc = Locs.getRegisterLocation(13);
  EXPECT_TRUE(OptionalLoc.has_value());
  EXPECT_EQ(*OptionalLoc, Reg13Loc);
  OptionalLoc = Locs.getRegisterLocation(14);
  EXPECT_TRUE(OptionalLoc.has_value());
  EXPECT_EQ(*OptionalLoc, Reg14Loc);
    Locs.removeRegisterLocation(13);
  EXPECT_FALSE(Locs.getRegisterLocation(13).has_value());
  EXPECT_TRUE(Locs.hasLocations());
  expectDumpResult(Locs, "reg12=[CFA+4], reg14=same");
  Locs.removeRegisterLocation(14);
  EXPECT_FALSE(Locs.getRegisterLocation(14).has_value());
  EXPECT_TRUE(Locs.hasLocations());
  expectDumpResult(Locs, "reg12=[CFA+4]");
  Locs.removeRegisterLocation(12);
  EXPECT_FALSE(Locs.getRegisterLocation(12).has_value());
  EXPECT_FALSE(Locs.hasLocations());
  expectDumpResult(Locs, "");
}
TEST(DWARFDebugFrame, UnwindTableEmptyRows) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
    EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
  EXPECT_TRUE(TestCIE.cfis().empty());
      Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const size_t ExpectedNumOfRows = 0;
  EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
    EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
  EXPECT_TRUE(TestFDE.cfis().empty());
      RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
}
TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
    EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_nop}), Succeeded());
  EXPECT_TRUE(!TestCIE.cfis().empty());
      Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const size_t ExpectedNumOfRows = 0;
  EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
    EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_nop}), Succeeded());
  EXPECT_TRUE(!TestFDE.cfis().empty());
      RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
}
TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
    constexpr uint8_t Reg = 12;
  constexpr uint8_t Offset = 32;
  EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
                    Succeeded());
                  EXPECT_THAT_ERROR(
      parseCFI(TestFDE, {dwarf::DW_CFA_set_loc, 0x00, 0x11, 0, 0, 0, 0, 0, 0,
                         dwarf::DW_CFA_set_loc, 0x00, 0x10, 0, 0, 0, 0, 0, 0}),
      Succeeded());
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(),
                    FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which"
                                      " must be greater than the current row "
                                      "address 0x1100"));
}
TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
    constexpr uint8_t Reg = 12;
  constexpr uint8_t Offset = 32;
  EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
                    Succeeded());
          EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_restore_state}),
                    Succeeded());
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(),
                    FailedWithMessage("DW_CFA_restore_state without a matching "
                                      "previous DW_CFA_remember_state"));
}
TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
    constexpr uint8_t Reg = 12;
  constexpr uint8_t Offset = 32;
  EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, Reg, Offset}),
                    Succeeded());
            EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_GNU_window_save}),
                    Succeeded());
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(),
                    FailedWithMessage("DW_CFA opcode 0x2d is not supported for "
                                      "architecture x86_64"));
}
TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
        EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
            EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset, 16}),
                    Succeeded());
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(),
                    FailedWithMessage("DW_CFA_def_cfa_offset found when CFA "
                                      "rule was not RegPlusOffset"));
}
TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
        EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
            EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_def_cfa_offset_sf, 4}),
                    Succeeded());
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(),
                    FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA "
                                      "rule was not RegPlusOffset"));
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) {
  dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
        constexpr uint8_t CFAReg = 12;
  EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa_register, CFAReg}),
                    Succeeded());
            EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 1u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getCFAValue(),
            dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg, 0));
}
TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) {
    dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      constexpr uint8_t CFAReg = 12;
  constexpr uint8_t CFAOffset = 32;
  constexpr uint8_t Reg = 13;
  constexpr uint8_t InReg = 14;
  EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
                                       dwarf::DW_CFA_register, Reg, InReg}),
                    Succeeded());
                EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_advance_loc | 4,
                                       dwarf::DW_CFA_advance_loc1,
                                       4,
                                       dwarf::DW_CFA_advance_loc2,
                                       4,
                                       0,
                                       dwarf::DW_CFA_advance_loc4,
                                       4,
                                       0,
                                       0,
                                       0,
                                       dwarf::DW_CFA_set_loc,
                                       0x14,
                                       0x10,
                                       0,
                                       0,
                                       0,
                                       0,
                                       0,
                                       0}),
                    Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  VerifyLocs.setRegisterLocation(
      Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 6u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
  EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
  EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
  EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
  EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[5].getAddress(), 0x1014u);
  EXPECT_EQ(Rows[5].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[5].getRegisterLocations(), VerifyLocs);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) {
      dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      constexpr uint8_t CFAReg = 12;
  constexpr uint8_t CFAOffset = 32;
  constexpr uint8_t Reg = 13;
  constexpr uint8_t InReg = 14;
  constexpr int32_t RegCFAOffset = -8;
  EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
                                       dwarf::DW_CFA_register, Reg, InReg}),
                    Succeeded());
              EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1,
                                       dwarf::DW_CFA_advance_loc | 4,
                                       dwarf::DW_CFA_restore | Reg}),
                    Succeeded());
      dwarf::RegisterLocations VerifyLocs1;
  VerifyLocs1.setRegisterLocation(
      Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset));
  dwarf::RegisterLocations VerifyLocs2;
  VerifyLocs2.setRegisterLocation(
      Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 2u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
  EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
  EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) {
      dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      constexpr uint8_t CFAReg = 12;
  constexpr uint8_t CFAOffset = 32;
  constexpr uint8_t Reg = 13;
  constexpr uint8_t InReg = 14;
  constexpr int32_t RegCFAOffset = -8;
  EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg, CFAOffset,
                                       dwarf::DW_CFA_register, Reg, InReg}),
                    Succeeded());
              EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_offset | Reg, 1,
                                       dwarf::DW_CFA_advance_loc | 4,
                                       dwarf::DW_CFA_restore_extended, Reg}),
                    Succeeded());
      dwarf::RegisterLocations VerifyLocs1;
  VerifyLocs1.setRegisterLocation(
      Reg, dwarf::UnwindLocation::createAtCFAPlusOffset(RegCFAOffset));
  dwarf::RegisterLocations VerifyLocs2;
  VerifyLocs2.setRegisterLocation(
      Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 2u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
  EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
  EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) {
        dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
                    Succeeded());
            constexpr uint8_t Reg1 = 14;
  constexpr uint8_t Reg2 = 15;
  constexpr uint8_t Reg3 = 16;
  constexpr uint8_t Neg1SLEB = 0x7f;
  EXPECT_THAT_ERROR(
      parseCFI(TestFDE,
               {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_offset_extended,
                Reg2, 2, dwarf::DW_CFA_offset_extended_sf, Reg3, Neg1SLEB}),
      Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  VerifyLocs.setRegisterLocation(
      Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
  VerifyLocs.setRegisterLocation(
      Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
  VerifyLocs.setRegisterLocation(
      Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 1u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) {
      dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
                    Succeeded());
            constexpr uint8_t Reg1 = 14;
  constexpr uint8_t Reg2 = 15;
  constexpr uint8_t Neg1SLEB = 0x7f;
  EXPECT_THAT_ERROR(
      parseCFI(TestFDE, {dwarf::DW_CFA_val_offset, Reg1, 1,
                         dwarf::DW_CFA_val_offset_sf, Reg2, Neg1SLEB}),
      Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  VerifyLocs.setRegisterLocation(
      Reg1, dwarf::UnwindLocation::createIsCFAPlusOffset(-8));
  VerifyLocs.setRegisterLocation(
      Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 1u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) {
    dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
                    Succeeded());
          constexpr uint8_t Reg1 = 14;
  EXPECT_THAT_ERROR(
      parseCFI(TestFDE, {dwarf::DW_CFA_nop, dwarf::DW_CFA_offset | Reg1, 1}),
      Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  VerifyLocs.setRegisterLocation(
      Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 1u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) {
      dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
                    Succeeded());
                                            constexpr uint8_t Reg1 = 14;
  constexpr uint8_t Reg2 = 15;
  constexpr uint8_t Reg3 = 16;
  EXPECT_THAT_ERROR(
      parseCFI(TestFDE,
               {dwarf::DW_CFA_offset | Reg1, 1, dwarf::DW_CFA_advance_loc | 4,
                dwarf::DW_CFA_remember_state, dwarf::DW_CFA_offset | Reg2, 2,
                dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_remember_state,
                dwarf::DW_CFA_offset | Reg3, 3, dwarf::DW_CFA_advance_loc | 4,
                dwarf::DW_CFA_restore_state, dwarf::DW_CFA_advance_loc | 4,
                dwarf::DW_CFA_restore_state}),
      Succeeded());
      dwarf::RegisterLocations VerifyLocs1;
  VerifyLocs1.setRegisterLocation(
      Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
  dwarf::RegisterLocations VerifyLocs2;
  VerifyLocs2.setRegisterLocation(
      Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
  VerifyLocs2.setRegisterLocation(
      Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
  dwarf::RegisterLocations VerifyLocs3;
  VerifyLocs3.setRegisterLocation(
      Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
  VerifyLocs3.setRegisterLocation(
      Reg2, dwarf::UnwindLocation::createAtCFAPlusOffset(-16));
  VerifyLocs3.setRegisterLocation(
      Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 5u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs1);
  EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
  EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs2);
  EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
  EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs3);
  EXPECT_EQ(Rows[3].getAddress(), 0x100Cu);
  EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs2);
  EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
  EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs1);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) {
      dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
                    Succeeded());
          constexpr uint8_t Reg1 = 14;
  EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_undefined, Reg1}),
                    Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  VerifyLocs.setRegisterLocation(Reg1,
                                 dwarf::UnwindLocation::createUndefined());
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 1u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) {
      dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
                    Succeeded());
          constexpr uint8_t Reg1 = 14;
  EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_same_value, Reg1}),
                    Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame());
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 1u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) {
      dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
                    Succeeded());
          constexpr uint8_t Reg = 13;
  constexpr uint8_t InReg = 14;
  EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_register, Reg, InReg}),
                    Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  VerifyLocs.setRegisterLocation(
      Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 1u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) {
      dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
                    Succeeded());
          constexpr uint8_t Reg = 13;
  constexpr uint8_t AddrSize = 8;
  std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_expression, Reg, 1,
                                   dwarf::DW_OP_reg12};
  EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12};
  DataExtractor ExprData(ExprBytes, true, AddrSize);
  DWARFExpression Expr(ExprData, AddrSize);
  VerifyLocs.setRegisterLocation(
      Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 1u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) {
      dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, 12, 32}),
                    Succeeded());
          constexpr uint8_t Reg = 13;
  constexpr uint8_t AddrSize = 8;
  std::vector<uint8_t> CFIBytes = {dwarf::DW_CFA_val_expression, Reg, 1,
                                   dwarf::DW_OP_reg12};
  EXPECT_THAT_ERROR(parseCFI(TestFDE, CFIBytes), Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  std::vector<uint8_t> ExprBytes = {dwarf::DW_OP_reg12};
  DataExtractor ExprData(ExprBytes, true, AddrSize);
  DWARFExpression Expr(ExprData, AddrSize);
  VerifyLocs.setRegisterLocation(
      Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 1u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) {
        dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      constexpr uint8_t CFAReg1 = 12;
  constexpr uint8_t CFAOff1 = 32;
  constexpr uint8_t CFAReg2 = 13;
  constexpr uint8_t CFAOff2 = 48;
  constexpr uint8_t Reg = 13;
  constexpr uint8_t InReg = 14;
  EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_def_cfa, CFAReg1, CFAOff1,
                                       dwarf::DW_CFA_register, Reg, InReg}),
                    Succeeded());
        EXPECT_THAT_ERROR(
      parseCFI(
          TestFDE,
          {
              dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register,
              CFAReg2, dwarf::DW_CFA_advance_loc | 4,
              dwarf::DW_CFA_def_cfa_offset, CFAOff2,
              dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf,
              0x7c,               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1,
              0x7a,           }),
      Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  VerifyLocs.setRegisterLocation(
      Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 5u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(
      Rows[0].getCFAValue(),
      dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1));
  EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
  EXPECT_EQ(
      Rows[1].getCFAValue(),
      dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1));
  EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
  EXPECT_EQ(
      Rows[2].getCFAValue(),
      dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2));
  EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
  EXPECT_EQ(
      Rows[3].getCFAValue(),
      dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1));
  EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
  EXPECT_EQ(
      Rows[4].getCFAValue(),
      dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2));
  EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
}
TEST(DWARFDebugFrame, UnwindTable_DW_CFA_LLVM_def_aspace_cfa) {
          dwarf::CIE TestCIE = createCIE(false,
                                 0x0,
                                 0xff);
  dwarf::FDE TestFDE(true,
                     0x3333abcdabcd,
                     0x4444abcdabcd,
                     0x1111abcdabcd,
                     0x1000,
                     0x1000,
                     &TestCIE,
                     None,
                     Triple::x86_64);
      constexpr uint8_t CFAReg1 = 12;
  constexpr uint8_t CFAOff1 = 32;
  constexpr uint8_t CFAReg2 = 13;
  constexpr uint8_t CFAOff2 = 48;
  constexpr uint8_t Reg = 13;
  constexpr uint8_t InReg = 14;
  constexpr uint8_t AddrSpace = 2;
  EXPECT_THAT_ERROR(
      parseCFI(TestCIE, {dwarf::DW_CFA_LLVM_def_aspace_cfa, CFAReg1, CFAOff1,
                         AddrSpace, dwarf::DW_CFA_register, Reg, InReg}),
      Succeeded());
        EXPECT_THAT_ERROR(
      parseCFI(
          TestFDE,
          {
              dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_register,
              CFAReg2, dwarf::DW_CFA_advance_loc | 4,
              dwarf::DW_CFA_def_cfa_offset, CFAOff2,
              dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_offset_sf,
              0x7c,               dwarf::DW_CFA_advance_loc | 4, dwarf::DW_CFA_def_cfa_sf, CFAReg1,
              0x7a,           }),
      Succeeded());
      dwarf::RegisterLocations VerifyLocs;
  VerifyLocs.setRegisterLocation(
      Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
    Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
  EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
  const dwarf::UnwindTable &Rows = RowsOrErr.get();
  EXPECT_EQ(Rows.size(), 5u);
  EXPECT_EQ(Rows[0].getAddress(), 0x1000u);
  EXPECT_EQ(Rows[0].getCFAValue(),
            dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff1,
                                                              AddrSpace));
  EXPECT_EQ(Rows[0].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[0].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[1].getAddress(), 0x1004u);
  EXPECT_EQ(Rows[1].getCFAValue(),
            dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1,
                                                              AddrSpace));
  EXPECT_EQ(Rows[1].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[1].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[2].getAddress(), 0x1008u);
  EXPECT_EQ(Rows[2].getCFAValue(),
            dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff2,
                                                              AddrSpace));
  EXPECT_EQ(Rows[2].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[2].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[3].getAddress(), 0x100cu);
  EXPECT_EQ(Rows[3].getCFAValue(),
            dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg2, CFAOff1,
                                                              AddrSpace));
  EXPECT_EQ(Rows[3].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[3].getRegisterLocations(), VerifyLocs);
  EXPECT_EQ(Rows[4].getAddress(), 0x1010u);
  EXPECT_EQ(Rows[4].getCFAValue(),
            dwarf::UnwindLocation::createIsRegisterPlusOffset(CFAReg1, CFAOff2,
                                                              AddrSpace));
  EXPECT_EQ(Rows[4].getRegisterLocations().size(), 1u);
  EXPECT_EQ(Rows[4].getRegisterLocations(), VerifyLocs);
}
}