aleksandr.urakov updated this revision to Diff 219853.
aleksandr.urakov added a comment.

Update diff due to Pavel's requests.


Repository:
  rLLDB LLDB

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67347/new/

https://reviews.llvm.org/D67347

Files:
  lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
  lldb/include/lldb/Symbol/ICallFrameInfo.h
  lldb/include/lldb/Symbol/ObjectFile.h
  lldb/include/lldb/Symbol/UnwindTable.h
  lldb/include/lldb/lldb-forward.h
  lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
  lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
  lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  lldb/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt
  lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
  lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
  lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp
  lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.h
  lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
  lldb/source/Symbol/DWARFCallFrameInfo.cpp
  lldb/source/Symbol/FuncUnwinders.cpp
  lldb/source/Symbol/ObjectFile.cpp
  lldb/source/Symbol/Type.cpp
  lldb/source/Symbol/UnwindTable.cpp
  lldb/unittests/ObjectFile/CMakeLists.txt
  lldb/unittests/ObjectFile/PECOFF/CMakeLists.txt
  lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp
  llvm/include/llvm/Support/Win64EH.h

Index: llvm/include/llvm/Support/Win64EH.h
===================================================================
--- llvm/include/llvm/Support/Win64EH.h
+++ llvm/include/llvm/Support/Win64EH.h
@@ -30,7 +30,9 @@
   UOP_SetFPReg,
   UOP_SaveNonVol,
   UOP_SaveNonVolBig,
-  UOP_SaveXMM128 = 8,
+  UOP_Epilog,
+  UOP_SpareCode,
+  UOP_SaveXMM128,
   UOP_SaveXMM128Big,
   UOP_PushMachFrame,
   // The following set of unwind opcodes is for ARM64.  They are documented at
Index: lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp
===================================================================
--- /dev/null
+++ lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp
@@ -0,0 +1,336 @@
+//===-- TestPECallFrameInfo.cpp ------------------------------*- C++ -*-===//
+//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+#include "TestingSupport/TestUtilities.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ICallFrameInfo.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "llvm/Testing/Support/Error.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+class PECallFrameInfoTest : public testing::Test {
+public:
+  void SetUp() override {
+    FileSystem::Initialize();
+    ObjectFilePECOFF::Initialize();
+  }
+
+  void TearDown() override {
+    ObjectFilePECOFF::Terminate();
+    FileSystem::Terminate();
+  }
+
+protected:
+  void GetUnwindPlan(addr_t file_addr, UnwindPlan &plan) const;
+};
+
+void PECallFrameInfoTest::GetUnwindPlan(addr_t file_addr, UnwindPlan &plan) const {
+  llvm::Expected<TestFile> ExpectedFile = TestFile::fromYaml(
+      R"(
+--- !COFF
+OptionalHeader:  
+  AddressOfEntryPoint: 0
+  ImageBase:       16777216
+  SectionAlignment: 4096
+  FileAlignment:   512
+  MajorOperatingSystemVersion: 6
+  MinorOperatingSystemVersion: 0
+  MajorImageVersion: 0
+  MinorImageVersion: 0
+  MajorSubsystemVersion: 6
+  MinorSubsystemVersion: 0
+  Subsystem:       IMAGE_SUBSYSTEM_WINDOWS_CUI
+  DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT ]
+  SizeOfStackReserve: 1048576
+  SizeOfStackCommit: 4096
+  SizeOfHeapReserve: 1048576
+  SizeOfHeapCommit: 4096
+  ExportTable:     
+    RelativeVirtualAddress: 0
+    Size:            0
+  ImportTable:     
+    RelativeVirtualAddress: 0
+    Size:            0
+  ResourceTable:   
+    RelativeVirtualAddress: 0
+    Size:            0
+  ExceptionTable:  
+    RelativeVirtualAddress: 12288
+    Size:            60
+  CertificateTable: 
+    RelativeVirtualAddress: 0
+    Size:            0
+  BaseRelocationTable: 
+    RelativeVirtualAddress: 0
+    Size:            0
+  Debug:           
+    RelativeVirtualAddress: 0
+    Size:            0
+  Architecture:    
+    RelativeVirtualAddress: 0
+    Size:            0
+  GlobalPtr:       
+    RelativeVirtualAddress: 0
+    Size:            0
+  TlsTable:        
+    RelativeVirtualAddress: 0
+    Size:            0
+  LoadConfigTable: 
+    RelativeVirtualAddress: 0
+    Size:            0
+  BoundImport:     
+    RelativeVirtualAddress: 0
+    Size:            0
+  IAT:             
+    RelativeVirtualAddress: 0
+    Size:            0
+  DelayImportDescriptor: 
+    RelativeVirtualAddress: 0
+    Size:            0
+  ClrRuntimeHeader: 
+    RelativeVirtualAddress: 0
+    Size:            0
+header:          
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE ]
+sections:        
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    VirtualAddress:  4096
+    VirtualSize:     4096
+  - Name:            .rdata
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+    VirtualAddress:  8192
+    VirtualSize:     68
+    SectionData:     010C06000C3208F006E00470036002302105020005540D0000100000001100000020000019400E352F74670028646600213465001A3315015E000EF00CE00AD008C00650
+
+
+# Unwind info at 0x2000:
+# 01 0C 06 00    No chained info, prolog size = 0xC, unwind codes size is 6 words, no frame register
+# 0C 32          UOP_AllocSmall(2) 3 * 8 + 8 bytes, offset in prolog is 0xC
+# 08 F0          UOP_PushNonVol(0) R15(0xF), offset in prolog is 8
+# 06 E0          UOP_PushNonVol(0) R14(0xE), offset in prolog is 6
+# 04 70          UOP_PushNonVol(0) RDI(7), offset in prolog is 4
+# 03 60          UOP_PushNonVol(0) RSI(6), offset in prolog is 3
+# 02 30          UOP_PushNonVol(0) RBX(3), offset in prolog is 2
+# Corresponding prolog:
+# 00    push    rbx
+# 02    push    rsi
+# 03    push    rdi
+# 04    push    r14
+# 06    push    r15
+# 08    sub     rsp, 20h
+
+# Unwind info at 0x2010:
+# 21 05 02 00    Has chained info, prolog size = 5, unwind codes size is 2 words, no frame register
+# 05 54 0D 00    UOP_SaveNonVol(4) RBP(5) to RSP + 0xD * 8, offset in prolog is 5
+# Chained runtime function:
+# 00 10 00 00    Start address is 0x1000
+# 00 11 00 00    End address is 0x1100
+# 00 20 00 00    Unwind info RVA is 0x2000
+# Corresponding prolog:
+# 00    mov     [rsp+68h], rbp
+
+# Unwind info at 0x2024:
+# 19 40 0E 35    No chained info, prolog size = 0x40, unwind codes size is 0xE words, frame register is RBP, frame register offset is RSP + 3 * 16
+# 2F 74 67 00    UOP_SaveNonVol(4) RDI(7) to RSP + 0x67 * 8, offset in prolog is 0x2F
+# 28 64 66 00    UOP_SaveNonVol(4) RSI(6) to RSP + 0x66 * 8, offset in prolog is 0x28
+# 21 34 65 00    UOP_SaveNonVol(4) RBX(3) to RSP + 0x65 * 8, offset in prolog is 0x21
+# 1A 33          UOP_SetFPReg(3), offset in prolog is 0x1A
+# 15 01 5E 00    UOP_AllocLarge(1) 0x5E * 8 bytes, offset in prolog is 0x15
+# 0E F0          UOP_PushNonVol(0) R15(0xF), offset in prolog is 0xE
+# 0C E0          UOP_PushNonVol(0) R14(0xE), offset in prolog is 0xC
+# 0A D0          UOP_PushNonVol(0) R13(0xD), offset in prolog is 0xA
+# 08 C0          UOP_PushNonVol(0) R12(0xC), offset in prolog is 8
+# 06 50          UOP_PushNonVol(0) RBP(5), offset in prolog is 6
+# Corresponding prolog:
+# 00    mov     [rsp+8], rcx
+# 05    push    rbp
+# 06    push    r12
+# 08    push    r13
+# 0A    push    r14
+# 0C    push    r15
+# 0E    sub     rsp, 2F0h
+# 15    lea     rbp, [rsp+30h]
+# 1A    mov     [rbp+2F8h], rbx
+# 21    mov     [rbp+300h], rsi
+# 28    mov     [rbp+308h], rdi
+
+  - Name:            .pdata
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+    VirtualAddress:  12288
+    VirtualSize:     60
+    SectionData:     000000000000000000000000000000000000000000000000001000000011000000200000001100000012000010200000001200000013000024200000
+
+# 00 00 00 00
+# 00 00 00 00    Test correct processing of empty runtime functions at begin
+# 00 00 00 00
+
+# 00 00 00 00
+# 00 00 00 00    Test correct processing of empty runtime functions at begin
+# 00 00 00 00
+
+# 00 10 00 00    Start address is 0x1000
+# 00 11 00 00    End address is 0x1100
+# 00 20 00 00    Unwind info RVA is 0x2000
+
+# 00 11 00 00    Start address is 0x1100
+# 00 12 00 00    End address is 0x1200
+# 10 20 00 00    Unwind info RVA is 0x2010
+
+# 00 12 00 00    Start address is 0x1200
+# 00 13 00 00    End address is 0x1300
+# 24 20 00 00    Unwind info RVA is 0x2024
+
+symbols:         []
+...
+)");
+  ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
+
+  ModuleSP module_sp = std::make_shared<Module>(ModuleSpec(FileSpec(ExpectedFile->name())));
+  ObjectFile *object_file = module_sp->GetObjectFile();
+  ASSERT_NE(object_file, nullptr);
+
+  std::unique_ptr<ICallFrameInfo> cfi = object_file->CreateEHCallFrameInfo();
+  ASSERT_NE(cfi.get(), nullptr);
+
+  SectionList *sect_list = object_file->GetSectionList();
+  ASSERT_NE(sect_list, nullptr);
+
+  EXPECT_TRUE(cfi->GetUnwindPlan(Address(file_addr, sect_list), plan));
+}
+
+TEST_F(PECallFrameInfoTest, Basic_eh) {
+  UnwindPlan plan(eRegisterKindLLDB);
+  GetUnwindPlan(0x1001080, plan);
+  EXPECT_EQ(plan.GetRowCount(), 7);
+
+  UnwindPlan::Row row;
+  row.SetOffset(0);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 8);
+  row.SetRegisterLocationToIsCFAPlusOffset(lldb_rsp_x86_64, 0, true);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rip_x86_64, -8, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(0), row);
+
+  row.SetOffset(2);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x10);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rbx_x86_64, -0x10, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(1), row);
+
+  row.SetOffset(3);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x18);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rsi_x86_64, -0x18, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(2), row);
+
+  row.SetOffset(4);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x20);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rdi_x86_64, -0x20, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(3), row);
+
+  row.SetOffset(6);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x28);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_r14_x86_64, -0x28, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(4), row);
+
+  row.SetOffset(8);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x30);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_r15_x86_64, -0x30, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(5), row);
+
+  row.SetOffset(0xC);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x50);
+  EXPECT_EQ(*plan.GetRowAtIndex(6), row);
+}
+
+TEST_F(PECallFrameInfoTest, Chained_eh) {
+  UnwindPlan plan(eRegisterKindLLDB);
+  GetUnwindPlan(0x1001180, plan);
+  EXPECT_EQ(plan.GetRowCount(), 2);
+
+  UnwindPlan::Row row;
+  row.SetOffset(0);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x50);
+  row.SetRegisterLocationToIsCFAPlusOffset(lldb_rsp_x86_64, 0, true);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rip_x86_64, -8, true);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rbx_x86_64, -0x10, true);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rsi_x86_64, -0x18, true);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rdi_x86_64, -0x20, true);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_r14_x86_64, -0x28, true);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_r15_x86_64, -0x30, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(0), row);
+
+  row.SetOffset(5);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rbp_x86_64, 0x18, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(1), row);
+}
+
+TEST_F(PECallFrameInfoTest, Frame_reg_eh) {
+  UnwindPlan plan(eRegisterKindLLDB);
+  GetUnwindPlan(0x1001280, plan);
+  EXPECT_EQ(plan.GetRowCount(), 11);
+
+  UnwindPlan::Row row;
+  row.SetOffset(0);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 8);
+  row.SetRegisterLocationToIsCFAPlusOffset(lldb_rsp_x86_64, 0, true);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rip_x86_64, -8, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(0), row);
+
+  row.SetOffset(6);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x10);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rbp_x86_64, -0x10, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(1), row);
+
+  row.SetOffset(8);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x18);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_r12_x86_64, -0x18, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(2), row);
+
+  row.SetOffset(0xA);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x20);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_r13_x86_64, -0x20, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(3), row);
+
+  row.SetOffset(0xC);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x28);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_r14_x86_64, -0x28, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(4), row);
+
+  row.SetOffset(0xE);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x30);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_r15_x86_64, -0x30, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(5), row);
+
+  row.SetOffset(0x15);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64, 0x320);
+  EXPECT_EQ(*plan.GetRowAtIndex(6), row);
+
+  row.SetOffset(0x1A);
+  row.GetCFAValue().SetIsRegisterPlusOffset(lldb_rbp_x86_64, 0x2F0);
+  EXPECT_EQ(*plan.GetRowAtIndex(7), row);
+
+  row.SetOffset(0x21);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rbx_x86_64, 8, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(8), row);
+
+  row.SetOffset(0x28);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rsi_x86_64, 0x10, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(9), row);
+
+  row.SetOffset(0x2F);
+  row.SetRegisterLocationToAtCFAPlusOffset(lldb_rdi_x86_64, 0x18, true);
+  EXPECT_EQ(*plan.GetRowAtIndex(10), row);
+}
Index: lldb/unittests/ObjectFile/PECOFF/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/unittests/ObjectFile/PECOFF/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_lldb_unittest(ObjectFilePECOFFTests
+  TestPECallFrameInfo.cpp
+
+  LINK_LIBS
+    lldbUtilityHelpers
+    lldbPluginObjectFilePECOFF
+    LLVMTestingSupport
+  )
Index: lldb/unittests/ObjectFile/CMakeLists.txt
===================================================================
--- lldb/unittests/ObjectFile/CMakeLists.txt
+++ lldb/unittests/ObjectFile/CMakeLists.txt
@@ -1,2 +1,3 @@
 add_subdirectory(Breakpad)
 add_subdirectory(ELF)
+add_subdirectory(PECOFF)
Index: lldb/source/Symbol/UnwindTable.cpp
===================================================================
--- lldb/source/Symbol/UnwindTable.cpp
+++ lldb/source/Symbol/UnwindTable.cpp
@@ -47,34 +47,10 @@
   if (!object_file)
     return;
 
-  SectionList *sl = m_module.GetSectionList();
-  if (!sl)
-    return;
-
-  SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true);
-  if (sect.get()) {
-    m_eh_frame_up.reset(
-        new DWARFCallFrameInfo(*object_file, sect, DWARFCallFrameInfo::EH));
-  }
-
-  sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true);
-  if (sect) {
-    m_debug_frame_up.reset(
-        new DWARFCallFrameInfo(*object_file, sect, DWARFCallFrameInfo::DWARF));
-  }
-
-  sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true);
-  if (sect) {
-    m_compact_unwind_up.reset(new CompactUnwindInfo(*object_file, sect));
-  }
-
-  sect = sl->FindSectionByType(eSectionTypeARMexidx, true);
-  if (sect) {
-    SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true);
-    if (sect_extab.get()) {
-      m_arm_unwind_up.reset(new ArmUnwindInfo(*object_file, sect, sect_extab));
-    }
-  }
+  m_eh_frame_up = object_file->CreateEHCallFrameInfo();
+  m_debug_frame_up = object_file->CreateDebugCallFrameInfo();
+  m_compact_unwind_up = object_file->CreateCompactUnwindInfo();
+  m_arm_unwind_up = object_file->CreateArmUnwindInfo();
 }
 
 UnwindTable::~UnwindTable() {}
@@ -83,12 +59,6 @@
                                                           SymbolContext &sc) {
   AddressRange range;
 
-  // First check the symbol context
-  if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
-                         false, range) &&
-      range.GetBaseAddress().IsValid())
-    return range;
-
   // Does the eh_frame unwind info has a function bounds for this addr?
   if (m_eh_frame_up && m_eh_frame_up->GetAddressRange(addr, range))
     return range;
@@ -97,6 +67,12 @@
   if (m_debug_frame_up && m_debug_frame_up->GetAddressRange(addr, range))
     return range;
 
+  // Last check the symbol context
+  if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
+                         false, range) &&
+      range.GetBaseAddress().IsValid())
+    return range;
+
   return llvm::None;
 }
 
@@ -162,12 +138,12 @@
   s.EOL();
 }
 
-DWARFCallFrameInfo *UnwindTable::GetEHFrameInfo() {
+ICallFrameInfo *UnwindTable::GetEHFrameInfo() {
   Initialize();
   return m_eh_frame_up.get();
 }
 
-DWARFCallFrameInfo *UnwindTable::GetDebugFrameInfo() {
+ICallFrameInfo *UnwindTable::GetDebugFrameInfo() {
   Initialize();
   return m_debug_frame_up.get();
 }
Index: lldb/source/Symbol/Type.cpp
===================================================================
--- lldb/source/Symbol/Type.cpp
+++ lldb/source/Symbol/Type.cpp
@@ -462,6 +462,7 @@
 
 bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) {
   // TODO: This needs to consider the correct type system to use.
+  compiler_type_resolve_state = eResolveStateForward;
   Type *encoding_type = nullptr;
   if (!m_compiler_type.IsValid()) {
     encoding_type = GetEncodingType();
Index: lldb/source/Symbol/ObjectFile.cpp
===================================================================
--- lldb/source/Symbol/ObjectFile.cpp
+++ lldb/source/Symbol/ObjectFile.cpp
@@ -22,6 +22,9 @@
 #include "lldb/Utility/RegularExpression.h"
 #include "lldb/Utility/Timer.h"
 #include "lldb/lldb-private.h"
+#include "lldb/Symbol/DWARFCallFrameInfo.h"
+#include "lldb/Symbol/CompactUnwindInfo.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -671,6 +674,60 @@
   return loadables;
 }
 
+std::unique_ptr<ICallFrameInfo> ObjectFile::CreateEHCallFrameInfo() {
+  SectionList *sl = GetSectionList();
+  if (!sl)
+    return {};
+
+  SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true);
+  if (!sect)
+    return {};
+
+  return std::make_unique<DWARFCallFrameInfo>(*this, sect,
+                                              DWARFCallFrameInfo::EH);
+}
+
+std::unique_ptr<ICallFrameInfo> ObjectFile::CreateDebugCallFrameInfo() {
+  SectionList *sl = GetSectionList();
+  if (!sl)
+    return {};
+
+  SectionSP sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true);
+  if (!sect)
+    return {};
+
+  return std::make_unique<DWARFCallFrameInfo>(*this, sect,
+                                              DWARFCallFrameInfo::DWARF);
+}
+
+std::unique_ptr<CompactUnwindInfo> ObjectFile::CreateCompactUnwindInfo() {
+  SectionList *sl = GetSectionList();
+  if (!sl)
+    return {};
+
+  SectionSP sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true);
+  if (!sect)
+    return {};
+
+  return std::make_unique<CompactUnwindInfo>(*this, sect);
+}
+
+std::unique_ptr<ArmUnwindInfo> ObjectFile::CreateArmUnwindInfo() {
+  SectionList *sl = GetSectionList();
+  if (!sl)
+    return {};
+
+  SectionSP sect = sl->FindSectionByType(eSectionTypeARMexidx, true);
+  if (!sect)
+    return {};
+
+  SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true);
+  if (!sect_extab)
+    return {};
+
+  return std::make_unique<ArmUnwindInfo>(*this, sect, sect_extab);
+}
+
 void ObjectFile::RelocateSection(lldb_private::Section *section)
 {
 }
Index: lldb/source/Symbol/FuncUnwinders.cpp
===================================================================
--- lldb/source/Symbol/FuncUnwinders.cpp
+++ lldb/source/Symbol/FuncUnwinders.cpp
@@ -104,7 +104,7 @@
 
   m_tried_unwind_plan_eh_frame = true;
   if (m_range.GetBaseAddress().IsValid()) {
-    DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
+    ICallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
     if (eh_frame) {
       m_unwind_plan_eh_frame_sp =
           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
@@ -122,7 +122,7 @@
 
   m_tried_unwind_plan_debug_frame = true;
   if (m_range.GetBaseAddress().IsValid()) {
-    DWARFCallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo();
+    ICallFrameInfo *debug_frame = m_unwind_table.GetDebugFrameInfo();
     if (debug_frame) {
       m_unwind_plan_debug_frame_sp =
           std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
Index: lldb/source/Symbol/DWARFCallFrameInfo.cpp
===================================================================
--- lldb/source/Symbol/DWARFCallFrameInfo.cpp
+++ lldb/source/Symbol/DWARFCallFrameInfo.cpp
@@ -451,8 +451,8 @@
 
     if (next_entry > m_cfi_data.GetByteSize() + 1) {
       Host::SystemLog(Host::eSystemLogError, "error: Invalid fde/cie next "
-                                             "entry offset of 0x%x found in "
-                                             "cie/fde at 0x%x\n",
+                      "entry offset of 0x%x found in "
+                      "cie/fde at 0x%x\n",
                       next_entry, current_entry);
       // Don't trust anything in this eh_frame section if we find blatantly
       // invalid data.
@@ -513,8 +513,8 @@
       m_fde_index.Append(fde);
     } else {
       Host::SystemLog(Host::eSystemLogError, "error: unable to find CIE at "
-                                             "0x%8.8x for cie_id = 0x%8.8x for "
-                                             "entry at 0x%8.8x.\n",
+                      "0x%8.8x for cie_id = 0x%8.8x for "
+                      "entry at 0x%8.8x.\n",
                       cie_offset, cie_id, current_entry);
     }
     offset = next_entry;
@@ -603,7 +603,7 @@
     offset += aug_data_len;
   }
   unwind_plan.SetUnwindPlanForSignalTrap(
-    strchr(cie->augmentation, 'S') ? eLazyBoolYes : eLazyBoolNo);
+      strchr(cie->augmentation, 'S') ? eLazyBoolYes : eLazyBoolNo);
 
   Address lsda_data;
   Address personality_function_ptr;
@@ -1011,13 +1011,13 @@
   return false;
 }
 
-void DWARFCallFrameInfo::ForEachFDEEntries(
-    const std::function<bool(lldb::addr_t, uint32_t, dw_offset_t)> &callback) {
+void DWARFCallFrameInfo::ForEachEntries(
+    const std::function<bool(lldb::addr_t, uint32_t)> &callback) {
   GetFDEIndex();
 
   for (size_t i = 0, c = m_fde_index.GetSize(); i < c; ++i) {
     const FDEEntryMap::Entry &entry = m_fde_index.GetEntryRef(i);
-    if (!callback(entry.base, entry.size, entry.data))
+    if (!callback(entry.base, entry.size))
       break;
   }
 }
Index: lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -762,7 +762,7 @@
 
     // Even with -fomit-frame-pointer, we can try eh_frame to get back on
     // track.
-    DWARFCallFrameInfo *eh_frame =
+    ICallFrameInfo *eh_frame =
         pc_module_sp->GetUnwindTable().GetEHFrameInfo();
     if (eh_frame) {
       unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
Index: lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.h
@@ -0,0 +1,53 @@
+//===-- PECallFrameInfo.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_PECallFrameInfo_h_
+#define liblldb_PECallFrameInfo_h_
+
+#include "lldb/Symbol/ICallFrameInfo.h"
+#include "lldb/Utility/DataExtractor.h"
+
+class ObjectFilePECOFF;
+
+namespace llvm {
+namespace Win64EH {
+
+struct RuntimeFunction;
+
+}
+} // namespace llvm
+
+class PECallFrameInfo : public virtual lldb_private::ICallFrameInfo {
+public:
+  explicit PECallFrameInfo(ObjectFilePECOFF &object_file,
+                           uint32_t exception_dir_rva,
+                           uint32_t exception_dir_size);
+
+  bool GetAddressRange(lldb_private::Address addr,
+                       lldb_private::AddressRange &range) override;
+
+  bool GetUnwindPlan(const lldb_private::Address &addr,
+                     lldb_private::UnwindPlan &unwind_plan) override;
+  bool GetUnwindPlan(const lldb_private::AddressRange &range,
+                     lldb_private::UnwindPlan &unwind_plan) override;
+
+  void GetFunctionAddressAndSizeVector(
+      FunctionAddressAndSizeVector &function_info) override;
+
+  void ForEachEntries(
+      const std::function<bool(lldb::addr_t, uint32_t)> &callback) override;
+
+private:
+  const llvm::Win64EH::RuntimeFunction *FindRuntimeFunctionItersectsWithRange(
+      const lldb_private::AddressRange &range) const;
+
+  ObjectFilePECOFF &m_object_file;
+  lldb_private::DataExtractor m_exception_data;
+};
+
+#endif // liblldb_PECallFrameInfo_h_
Index: lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp
@@ -0,0 +1,568 @@
+#include "PECallFrameInfo.h"
+
+#include "ObjectFilePECOFF.h"
+
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "llvm/Support/Win64EH.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm::Win64EH;
+
+template <typename T>
+static const T *TypedRead(const DataExtractor &data_extractor, offset_t &offset,
+                          offset_t size = sizeof(T)) {
+  return static_cast<const T *>(data_extractor.GetData(&offset, size));
+}
+
+struct EHInstruction {
+  enum class Type {
+    PUSH_REGISTER,
+    ALLOCATE,
+    SET_FRAME_POINTER_REGISTER,
+    SAVE_REGISTER
+  };
+
+  uint8_t offset;
+  Type type;
+  uint32_t reg;
+  uint32_t frame_offset;
+};
+
+using EHProgram = std::vector<EHInstruction>;
+
+class UnwindCodesIterator {
+public:
+  UnwindCodesIterator(ObjectFilePECOFF &object_file, uint32_t unwind_info_rva);
+
+  bool GetNext();
+  bool IsError() const { return m_error; }
+
+  const UnwindInfo *GetUnwindInfo() const { return m_unwind_info; }
+  const UnwindCode *GetUnwindCode() const { return m_unwind_code; }
+  bool IsChained() const { return m_chained; }
+
+private:
+  ObjectFilePECOFF &m_object_file;
+
+  bool m_error;
+
+  uint32_t m_unwind_info_rva;
+  DataExtractor m_unwind_info_data;
+  const UnwindInfo *m_unwind_info;
+
+  DataExtractor m_unwind_code_data;
+  offset_t m_unwind_code_offset;
+  const UnwindCode *m_unwind_code;
+
+  bool m_chained;
+};
+
+UnwindCodesIterator::UnwindCodesIterator(ObjectFilePECOFF &object_file,
+                                         uint32_t unwind_info_rva)
+    : m_object_file(object_file), m_error(false),
+      m_unwind_info_rva(unwind_info_rva),
+      m_unwind_info(nullptr), m_unwind_code_offset{}, m_unwind_code(nullptr),
+      m_chained(false) {}
+
+bool UnwindCodesIterator::GetNext() {
+  static constexpr int UNWIND_INFO_SIZE = 4;
+
+  m_error = false;
+  m_unwind_code = nullptr;
+  while (!m_unwind_code) {
+    if (!m_unwind_info) {
+      m_unwind_info_data =
+          m_object_file.ReadImageDataByRVA(m_unwind_info_rva, UNWIND_INFO_SIZE);
+
+      offset_t offset = 0;
+      m_unwind_info =
+          TypedRead<UnwindInfo>(m_unwind_info_data, offset, UNWIND_INFO_SIZE);
+      if (!m_unwind_info) {
+        m_error = true;
+        break;
+      }
+
+      m_unwind_code_data = m_object_file.ReadImageDataByRVA(
+          m_unwind_info_rva + UNWIND_INFO_SIZE,
+          m_unwind_info->NumCodes * sizeof(UnwindCode));
+      m_unwind_code_offset = 0;
+    }
+
+    if (m_unwind_code_offset < m_unwind_code_data.GetByteSize()) {
+      m_unwind_code =
+          TypedRead<UnwindCode>(m_unwind_code_data, m_unwind_code_offset);
+      m_error = !m_unwind_code;
+      break;
+    }
+
+    if (!(m_unwind_info->getFlags() & UNW_ChainInfo))
+      break;
+
+    uint32_t runtime_function_rva =
+        m_unwind_info_rva + UNWIND_INFO_SIZE +
+        ((m_unwind_info->NumCodes + 1) & ~1) * sizeof(UnwindCode);
+    DataExtractor runtime_function_data = m_object_file.ReadImageDataByRVA(
+        runtime_function_rva, sizeof(RuntimeFunction));
+
+    offset_t offset = 0;
+    const auto *runtime_function =
+        TypedRead<RuntimeFunction>(runtime_function_data, offset);
+    if (!runtime_function) {
+      m_error = true;
+      break;
+    }
+
+    m_unwind_info_rva = runtime_function->UnwindInfoOffset;
+    m_unwind_info = nullptr;
+    m_chained = true;
+  }
+
+  return !!m_unwind_code;
+}
+
+class EHProgramBuilder {
+public:
+  EHProgramBuilder(ObjectFilePECOFF &object_file, uint32_t unwind_info_rva);
+
+  bool Build();
+
+  const EHProgram &GetProgram() const { return m_program; }
+
+private:
+  static uint32_t ConvertMachineToLLDBRegister(uint8_t machine_reg);
+  static uint32_t ConvertXMMToLLDBRegister(uint8_t xmm_reg);
+
+  bool ProcessUnwindCode(UnwindCode code);
+  void Finalize();
+
+  bool ParseBigOrScaledFrameOffset(uint32_t &result, bool big, uint32_t scale);
+  bool ParseBigFrameOffset(uint32_t &result);
+  bool ParseFrameOffset(uint32_t &result);
+
+  UnwindCodesIterator m_iterator;
+  EHProgram m_program;
+};
+
+EHProgramBuilder::EHProgramBuilder(ObjectFilePECOFF &object_file,
+                                   uint32_t unwind_info_rva)
+    : m_iterator(object_file, unwind_info_rva) {}
+
+bool EHProgramBuilder::Build() {
+  while (m_iterator.GetNext())
+    if (!ProcessUnwindCode(*m_iterator.GetUnwindCode()))
+      return false;
+
+  if (m_iterator.IsError())
+    return false;
+
+  Finalize();
+
+  return true;
+}
+
+uint32_t EHProgramBuilder::ConvertMachineToLLDBRegister(uint8_t machine_reg) {
+  static uint32_t machine_to_lldb_register[] = {
+      lldb_rax_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, lldb_rbx_x86_64,
+      lldb_rsp_x86_64, lldb_rbp_x86_64, lldb_rsi_x86_64, lldb_rdi_x86_64,
+      lldb_r8_x86_64,  lldb_r9_x86_64,  lldb_r10_x86_64, lldb_r11_x86_64,
+      lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64};
+
+  if (machine_reg >= llvm::array_lengthof(machine_to_lldb_register))
+    return LLDB_INVALID_REGNUM;
+
+  return machine_to_lldb_register[machine_reg];
+}
+
+uint32_t EHProgramBuilder::ConvertXMMToLLDBRegister(uint8_t xmm_reg) {
+  static uint32_t xmm_to_lldb_register[] = {
+      lldb_xmm0_x86_64,  lldb_xmm1_x86_64,  lldb_xmm2_x86_64,
+      lldb_xmm3_x86_64,  lldb_xmm4_x86_64,  lldb_xmm5_x86_64,
+      lldb_xmm6_x86_64,  lldb_xmm7_x86_64,  lldb_xmm8_x86_64,
+      lldb_xmm9_x86_64,  lldb_xmm10_x86_64, lldb_xmm11_x86_64,
+      lldb_xmm12_x86_64, lldb_xmm13_x86_64, lldb_xmm14_x86_64,
+      lldb_xmm15_x86_64};
+
+  if (xmm_reg >= llvm::array_lengthof(xmm_to_lldb_register))
+    return LLDB_INVALID_REGNUM;
+
+  return xmm_to_lldb_register[xmm_reg];
+}
+
+bool EHProgramBuilder::ProcessUnwindCode(UnwindCode code) {
+  uint8_t o = m_iterator.IsChained() ? 0 : code.u.CodeOffset;
+  uint8_t unwind_operation = code.getUnwindOp();
+  uint8_t operation_info = code.getOpInfo();
+
+  switch (unwind_operation) {
+  case UOP_PushNonVol: {
+    uint32_t r = ConvertMachineToLLDBRegister(operation_info);
+    if (r == LLDB_INVALID_REGNUM)
+      return false;
+
+    m_program.emplace_back(
+        EHInstruction{o, EHInstruction::Type::PUSH_REGISTER, r, 8});
+
+    return true;
+  }
+  case UOP_AllocLarge: {
+    uint32_t fo;
+    if (!ParseBigOrScaledFrameOffset(fo, operation_info, 8))
+      return false;
+
+    m_program.emplace_back(EHInstruction{o, EHInstruction::Type::ALLOCATE,
+                                         LLDB_INVALID_REGNUM, fo});
+
+    return true;
+  }
+  case UOP_AllocSmall: {
+    m_program.emplace_back(
+        EHInstruction{o, EHInstruction::Type::ALLOCATE, LLDB_INVALID_REGNUM,
+                      static_cast<uint32_t>(operation_info) * 8 + 8});
+    return true;
+  }
+  case UOP_SetFPReg: {
+    uint32_t fpr = LLDB_INVALID_REGNUM;
+    if (m_iterator.GetUnwindInfo()->getFrameRegister())
+      fpr = ConvertMachineToLLDBRegister(
+          m_iterator.GetUnwindInfo()->getFrameRegister());
+    if (fpr == LLDB_INVALID_REGNUM)
+      return false;
+
+    uint32_t fpro =
+        static_cast<uint32_t>(m_iterator.GetUnwindInfo()->getFrameOffset()) *
+        16;
+
+    m_program.emplace_back(EHInstruction{
+        o, EHInstruction::Type::SET_FRAME_POINTER_REGISTER, fpr, fpro});
+
+    return true;
+  }
+  case UOP_SaveNonVol:
+  case UOP_SaveNonVolBig: {
+    uint32_t r = ConvertMachineToLLDBRegister(operation_info);
+    if (r == LLDB_INVALID_REGNUM)
+      return false;
+
+    uint32_t fo;
+    if (!ParseBigOrScaledFrameOffset(fo, unwind_operation == UOP_SaveNonVolBig,
+                                     8))
+      return false;
+
+    m_program.emplace_back(
+        EHInstruction{o, EHInstruction::Type::SAVE_REGISTER, r, fo});
+
+    return true;
+  }
+  case UOP_Epilog: {
+    return m_iterator.GetNext();
+  }
+  case UOP_SpareCode: {
+    // ReSharper disable once CppIdenticalOperandsInBinaryExpression
+    return m_iterator.GetNext() && m_iterator.GetNext();
+  }
+  case UOP_SaveXMM128:
+  case UOP_SaveXMM128Big: {
+    uint32_t r = ConvertXMMToLLDBRegister(operation_info);
+    if (r == LLDB_INVALID_REGNUM)
+      return false;
+
+    uint32_t fo;
+    if (!ParseBigOrScaledFrameOffset(fo, unwind_operation == UOP_SaveXMM128Big,
+                                     16))
+      return false;
+
+    m_program.emplace_back(
+        EHInstruction{o, EHInstruction::Type::SAVE_REGISTER, r, fo});
+
+    return true;
+  }
+  case UOP_PushMachFrame: {
+    if (operation_info)
+      m_program.emplace_back(EHInstruction{o, EHInstruction::Type::ALLOCATE,
+                                           LLDB_INVALID_REGNUM, 8});
+    m_program.emplace_back(EHInstruction{o, EHInstruction::Type::PUSH_REGISTER,
+                                         lldb_rip_x86_64, 8});
+    m_program.emplace_back(EHInstruction{o, EHInstruction::Type::PUSH_REGISTER,
+                                         lldb_cs_x86_64, 8});
+    m_program.emplace_back(EHInstruction{o, EHInstruction::Type::PUSH_REGISTER,
+                                         lldb_rflags_x86_64, 8});
+    m_program.emplace_back(EHInstruction{o, EHInstruction::Type::PUSH_REGISTER,
+                                         lldb_rsp_x86_64, 8});
+    m_program.emplace_back(EHInstruction{o, EHInstruction::Type::PUSH_REGISTER,
+                                         lldb_ss_x86_64, 8});
+
+    return true;
+  }
+  default:
+    return false;
+  }
+}
+
+void EHProgramBuilder::Finalize() {
+  for (const EHInstruction &i : m_program)
+    if (i.reg == lldb_rip_x86_64)
+      return;
+
+  m_program.emplace_back(
+      EHInstruction{0, EHInstruction::Type::PUSH_REGISTER, lldb_rip_x86_64, 8});
+}
+
+bool EHProgramBuilder::ParseBigOrScaledFrameOffset(uint32_t &result, bool big,
+                                                   uint32_t scale) {
+  if (big) {
+    if (!ParseBigFrameOffset(result))
+      return false;
+  } else {
+    if (!ParseFrameOffset(result))
+      return false;
+
+    result *= scale;
+  }
+
+  return true;
+}
+
+bool EHProgramBuilder::ParseBigFrameOffset(uint32_t &result) {
+  if (!m_iterator.GetNext())
+    return false;
+
+  result = m_iterator.GetUnwindCode()->FrameOffset;
+
+  if (!m_iterator.GetNext())
+    return false;
+
+  result += static_cast<uint32_t>(m_iterator.GetUnwindCode()->FrameOffset)
+            << 16;
+
+  return true;
+}
+
+bool EHProgramBuilder::ParseFrameOffset(uint32_t &result) {
+  if (!m_iterator.GetNext())
+    return false;
+
+  result = m_iterator.GetUnwindCode()->FrameOffset;
+
+  return true;
+}
+
+class EHProgramRange {
+public:
+  EHProgramRange(EHProgram::const_iterator begin,
+                 EHProgram::const_iterator end);
+
+  std::unique_ptr<UnwindPlan::Row> BuildUnwindPlanRow() const;
+
+private:
+  int32_t GetCFAFrameOffset() const;
+
+  EHProgram::const_iterator m_begin;
+  EHProgram::const_iterator m_end;
+};
+
+EHProgramRange::EHProgramRange(EHProgram::const_iterator begin,
+                               EHProgram::const_iterator end)
+    : m_begin(begin), m_end(end) {}
+
+std::unique_ptr<UnwindPlan::Row> EHProgramRange::BuildUnwindPlanRow() const {
+  std::unique_ptr<UnwindPlan::Row> row = std::make_unique<UnwindPlan::Row>();
+
+  if (m_begin != m_end)
+    row->SetOffset(m_begin->offset);
+
+  int32_t cfa_frame_offset = GetCFAFrameOffset();
+
+  bool frame_pointer_found = false;
+  for (EHProgram::const_iterator it = m_begin; it != m_end; ++it) {
+    switch (it->type) {
+    case EHInstruction::Type::SET_FRAME_POINTER_REGISTER:
+      row->GetCFAValue().SetIsRegisterPlusOffset(it->reg, cfa_frame_offset -
+                                                              it->frame_offset);
+      frame_pointer_found = true;
+      break;
+    default:
+      break;
+    }
+    if (frame_pointer_found)
+      break;
+  }
+  if (!frame_pointer_found)
+    row->GetCFAValue().SetIsRegisterPlusOffset(lldb_rsp_x86_64,
+                                               cfa_frame_offset);
+
+  int32_t rsp_frame_offset = 0;
+  for (EHProgram::const_iterator it = m_begin; it != m_end; ++it) {
+    switch (it->type) {
+    case EHInstruction::Type::PUSH_REGISTER:
+      row->SetRegisterLocationToAtCFAPlusOffset(
+          it->reg, rsp_frame_offset - cfa_frame_offset, false);
+      rsp_frame_offset += it->frame_offset;
+      break;
+    case EHInstruction::Type::ALLOCATE:
+      rsp_frame_offset += it->frame_offset;
+      break;
+    case EHInstruction::Type::SAVE_REGISTER:
+      row->SetRegisterLocationToAtCFAPlusOffset(
+          it->reg, it->frame_offset - cfa_frame_offset, false);
+      break;
+    default:
+      break;
+    }
+  }
+
+  row->SetRegisterLocationToIsCFAPlusOffset(lldb_rsp_x86_64, 0, false);
+
+  return row;
+}
+
+int32_t EHProgramRange::GetCFAFrameOffset() const {
+  int32_t result = 0;
+
+  for (EHProgram::const_iterator it = m_begin; it != m_end; ++it) {
+    switch (it->type) {
+    case EHInstruction::Type::PUSH_REGISTER:
+    case EHInstruction::Type::ALLOCATE:
+      result += it->frame_offset;
+    default:
+      break;
+    }
+  }
+
+  return result;
+}
+
+PECallFrameInfo::PECallFrameInfo(ObjectFilePECOFF &object_file,
+                                 uint32_t exception_dir_rva,
+                                 uint32_t exception_dir_size)
+    : m_object_file(object_file),
+      m_exception_data(object_file.ReadImageDataByRVA(exception_dir_rva,
+                                                      exception_dir_size)) {}
+
+bool PECallFrameInfo::GetAddressRange(Address addr, AddressRange &range) {
+  range.Clear();
+
+  const RuntimeFunction *runtime_function =
+      FindRuntimeFunctionItersectsWithRange(AddressRange(addr, 1));
+  if (!runtime_function)
+    return false;
+
+  range.GetBaseAddress() =
+      m_object_file.GetAddress(runtime_function->StartAddress);
+  range.SetByteSize(runtime_function->EndAddress -
+                    runtime_function->StartAddress);
+
+  return true;
+}
+
+bool PECallFrameInfo::GetUnwindPlan(const Address &addr,
+                                    UnwindPlan &unwind_plan) {
+  return GetUnwindPlan(AddressRange(addr, 1), unwind_plan);
+}
+
+bool PECallFrameInfo::GetUnwindPlan(const AddressRange &range,
+                                    UnwindPlan &unwind_plan) {
+  unwind_plan.Clear();
+
+  unwind_plan.SetSourceName("PE EH info");
+  unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
+  unwind_plan.SetRegisterKind(eRegisterKindLLDB);
+
+  const RuntimeFunction *runtime_function =
+      FindRuntimeFunctionItersectsWithRange(range);
+  if (!runtime_function)
+    return false;
+
+  EHProgramBuilder builder(m_object_file, runtime_function->UnwindInfoOffset);
+  if (!builder.Build())
+    return false;
+
+  std::vector<UnwindPlan::RowSP> rows;
+
+  uint32_t last_offset = UINT32_MAX;
+  for (auto it = builder.GetProgram().begin(); it != builder.GetProgram().end();
+       ++it) {
+    if (it->offset == last_offset)
+      continue;
+
+    EHProgramRange program_range =
+        EHProgramRange(it, builder.GetProgram().end());
+    rows.push_back(program_range.BuildUnwindPlanRow());
+
+    last_offset = it->offset;
+  }
+
+  for (auto it = rows.rbegin(); it != rows.rend(); ++it)
+    unwind_plan.AppendRow(*it);
+
+  unwind_plan.SetPlanValidAddressRange(AddressRange(
+      m_object_file.GetAddress(runtime_function->StartAddress),
+      runtime_function->EndAddress - runtime_function->StartAddress));
+  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
+
+  return true;
+}
+
+void PECallFrameInfo::GetFunctionAddressAndSizeVector(
+    FunctionAddressAndSizeVector &function_info) {
+  function_info.Clear();
+
+  offset_t offset = 0;
+  while (offset < m_exception_data.GetByteSize()) {
+    const auto *runtime_function =
+        TypedRead<RuntimeFunction>(m_exception_data, offset);
+    if (!runtime_function)
+      break;
+
+    function_info.Append(
+        {m_object_file.GetFileAddress(runtime_function->StartAddress),
+         runtime_function->EndAddress - runtime_function->StartAddress});
+  }
+}
+
+void PECallFrameInfo::ForEachEntries(
+    const std::function<bool(addr_t, uint32_t)> &callback) {
+  offset_t offset = 0;
+  while (offset < m_exception_data.GetByteSize()) {
+    const auto *runtime_function =
+        TypedRead<RuntimeFunction>(m_exception_data, offset);
+    if (!runtime_function)
+      break;
+
+    if (!callback(m_object_file.GetFileAddress(runtime_function->StartAddress),
+                  runtime_function->EndAddress -
+                      runtime_function->StartAddress))
+      break;
+  }
+}
+
+const RuntimeFunction *PECallFrameInfo::FindRuntimeFunctionItersectsWithRange(
+    const AddressRange &range) const {
+  uint32_t rva = m_object_file.GetRVA(range.GetBaseAddress());
+  addr_t size = range.GetByteSize();
+
+  uint32_t begin = 0;
+  uint32_t end = m_exception_data.GetByteSize() / sizeof(RuntimeFunction);
+  while (begin < end) {
+    uint32_t curr = (begin + end) / 2;
+
+    offset_t offset = curr * sizeof(RuntimeFunction);
+    const auto *runtime_function =
+        TypedRead<RuntimeFunction>(m_exception_data, offset);
+    if (!runtime_function)
+      break;
+
+    if (runtime_function->StartAddress < rva + size &&
+        runtime_function->EndAddress > rva)
+      return runtime_function;
+
+    if (runtime_function->StartAddress >= rva + size)
+      end = curr;
+
+    if (runtime_function->EndAddress <= rva)
+      begin = curr + 1;
+  }
+
+  return nullptr;
+}
Index: lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
===================================================================
--- lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -135,7 +135,15 @@
 
   bool IsWindowsSubsystem();
 
+  uint32_t GetRVA(const lldb_private::Address &addr) const;
+  lldb_private::Address GetAddress(uint32_t rva);
+  lldb::addr_t GetFileAddress(uint32_t rva) const;
+
   lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size);
+  lldb_private::DataExtractor ReadImageDataByRVA(uint32_t rva, size_t size);
+
+  std::unique_ptr<lldb_private::ICallFrameInfo>
+  CreateEHCallFrameInfo() override;
 
 protected:
   bool NeedsEndianSwap() const;
@@ -216,6 +224,7 @@
   enum coff_data_dir_type {
     coff_data_dir_export_table = 0,
     coff_data_dir_import_table = 1,
+    coff_data_dir_exception_table = 3
   };
 
   typedef struct section_header {
Index: lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "ObjectFilePECOFF.h"
+#include "PECallFrameInfo.h"
 #include "WindowsMiniDump.h"
 
 #include "lldb/Core/FileSpecList.h"
@@ -514,7 +515,26 @@
   return success;
 }
 
+uint32_t ObjectFilePECOFF::GetRVA(const Address &addr) const {
+  return addr.GetFileAddress() - m_image_base;
+}
+
+Address ObjectFilePECOFF::GetAddress(uint32_t rva) {
+  SectionList *sect_list = GetSectionList();
+  if (!sect_list)
+    return Address(GetFileAddress(rva));
+
+  return Address(GetFileAddress(rva), sect_list);
+}
+
+lldb::addr_t ObjectFilePECOFF::GetFileAddress(uint32_t rva) const {
+  return m_image_base + rva;
+}
+
 DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) {
+  if (!size)
+    return {};
+
   if (m_file) {
     // A bit of a hack, but we intend to write to this buffer, so we can't
     // mmap it.
@@ -537,6 +557,15 @@
   return data;
 }
 
+DataExtractor ObjectFilePECOFF::ReadImageDataByRVA(uint32_t rva, size_t size) {
+  if (m_file) {
+    Address addr = GetAddress(rva);
+    rva = addr.GetSection()->GetFileOffset() + addr.GetOffset();
+  }
+
+  return ReadImageData(rva, size);
+}
+
 // ParseSectionHeaders
 bool ObjectFilePECOFF::ParseSectionHeaders(
     uint32_t section_header_data_offset) {
@@ -674,14 +703,8 @@
         uint32_t data_start =
             m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr;
 
-        uint32_t address_rva = data_start;
-        if (m_file) {
-          Address address(m_coff_header_opt.image_base + data_start, sect_list);
-          address_rva =
-              address.GetSection()->GetFileOffset() + address.GetOffset();
-        }
-        DataExtractor symtab_data =
-            ReadImageData(address_rva, m_coff_header_opt.data_dirs[0].vmsize);
+        DataExtractor symtab_data = ReadImageDataByRVA(
+            data_start, m_coff_header_opt.data_dirs[0].vmsize);
         lldb::offset_t offset = 0;
 
         // Read export_table header
@@ -736,6 +759,19 @@
   return m_symtab_up.get();
 }
 
+std::unique_ptr<ICallFrameInfo> ObjectFilePECOFF::CreateEHCallFrameInfo() {
+  if (coff_data_dir_exception_table >= m_coff_header_opt.data_dirs.size())
+    return {};
+
+  data_directory data_dir_exception =
+      m_coff_header_opt.data_dirs[coff_data_dir_exception_table];
+  if (!data_dir_exception.vmaddr)
+    return {};
+
+  return std::make_unique<PECallFrameInfo>(*this, data_dir_exception.vmaddr,
+                                           data_dir_exception.vmsize);
+}
+
 bool ObjectFilePECOFF::IsStripped() {
   // TODO: determine this for COFF
   return false;
Index: lldb/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt
+++ lldb/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_lldb_library(lldbPluginObjectFilePECOFF PLUGIN
   ObjectFilePECOFF.cpp
+  PECallFrameInfo.cpp
   WindowsMiniDump.cpp
 
   LINK_LIBS
Index: lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -2422,12 +2422,12 @@
           m_type != eTypeDebugInfo) {
         DWARFCallFrameInfo eh_frame(*this, eh_frame_section_sp,
                                     DWARFCallFrameInfo::EH);
-        DWARFCallFrameInfo::FunctionAddressAndSizeVector functions;
+        ICallFrameInfo::FunctionAddressAndSizeVector functions;
         eh_frame.GetFunctionAddressAndSizeVector(functions);
         addr_t text_base_addr = text_section_sp->GetFileAddress();
         size_t count = functions.GetSize();
         for (size_t i = 0; i < count; ++i) {
-          const DWARFCallFrameInfo::FunctionAddressAndSizeVector::Entry *func =
+          const ICallFrameInfo::FunctionAddressAndSizeVector::Entry *func =
               functions.GetEntryAtIndex(i);
           if (func) {
             FunctionStarts::Entry function_start_entry;
Index: lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
===================================================================
--- lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -297,7 +297,7 @@
                                   lldb::user_id_t section_id);
 
   void ParseUnwindSymbols(lldb_private::Symtab *symbol_table,
-                          lldb_private::DWARFCallFrameInfo *eh_frame);
+                          lldb_private::ICallFrameInfo *eh_frame);
 
   /// Relocates debug sections
   unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr,
Index: lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -18,7 +18,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Host/FileSystem.h"
-#include "lldb/Symbol/DWARFCallFrameInfo.h"
+#include "lldb/Symbol/ICallFrameInfo.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/Target.h"
@@ -2691,7 +2691,7 @@
       }
     }
 
-    if (DWARFCallFrameInfo *eh_frame =
+    if (ICallFrameInfo *eh_frame =
             GetModule()->GetUnwindTable().GetEHFrameInfo()) {
       if (m_symtab_up == nullptr)
         m_symtab_up.reset(new Symtab(this));
@@ -2751,7 +2751,7 @@
 }
 
 void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,
-                                       DWARFCallFrameInfo *eh_frame) {
+                                       ICallFrameInfo *eh_frame) {
   SectionList *section_list = GetSectionList();
   if (!section_list)
     return;
@@ -2763,8 +2763,8 @@
   // recalculate the index first.
   std::vector<Symbol> new_symbols;
 
-  eh_frame->ForEachFDEEntries([this, symbol_table, section_list, &new_symbols](
-      lldb::addr_t file_addr, uint32_t size, dw_offset_t) {
+  eh_frame->ForEachEntries([this, symbol_table, section_list, &new_symbols](
+      lldb::addr_t file_addr, uint32_t size) {
     Symbol *symbol = symbol_table->FindSymbolAtFileAddress(file_addr);
     if (symbol) {
       if (!symbol->GetByteSizeIsValid()) {
Index: lldb/include/lldb/lldb-forward.h
===================================================================
--- lldb/include/lldb/lldb-forward.h
+++ lldb/include/lldb/lldb-forward.h
@@ -69,7 +69,7 @@
 class ConnectionFileDescriptor;
 class ConstString;
 class CXXSyntheticChildren;
-class DWARFCallFrameInfo;
+class ICallFrameInfo;
 class DWARFDataExtractor;
 class DWARFExpression;
 class DataBuffer;
Index: lldb/include/lldb/Symbol/UnwindTable.h
===================================================================
--- lldb/include/lldb/Symbol/UnwindTable.h
+++ lldb/include/lldb/Symbol/UnwindTable.h
@@ -27,8 +27,8 @@
 
   ~UnwindTable();
 
-  lldb_private::DWARFCallFrameInfo *GetEHFrameInfo();
-  lldb_private::DWARFCallFrameInfo *GetDebugFrameInfo();
+  lldb_private::ICallFrameInfo *GetEHFrameInfo();
+  lldb_private::ICallFrameInfo *GetDebugFrameInfo();
 
   lldb_private::CompactUnwindInfo *GetCompactUnwindInfo();
 
@@ -71,8 +71,8 @@
   bool m_initialized; // delay some initialization until ObjectFile is set up
   std::mutex m_mutex;
 
-  std::unique_ptr<DWARFCallFrameInfo> m_eh_frame_up;
-  std::unique_ptr<DWARFCallFrameInfo> m_debug_frame_up;
+  std::unique_ptr<ICallFrameInfo> m_eh_frame_up;
+  std::unique_ptr<ICallFrameInfo> m_debug_frame_up;
   std::unique_ptr<CompactUnwindInfo> m_compact_unwind_up;
   std::unique_ptr<ArmUnwindInfo> m_arm_unwind_up;
 
Index: lldb/include/lldb/Symbol/ObjectFile.h
===================================================================
--- lldb/include/lldb/Symbol/ObjectFile.h
+++ lldb/include/lldb/Symbol/ObjectFile.h
@@ -650,6 +650,11 @@
   /// \return
   virtual std::vector<LoadableData> GetLoadableData(Target &target);
 
+  virtual std::unique_ptr<ICallFrameInfo> CreateEHCallFrameInfo();
+  virtual std::unique_ptr<ICallFrameInfo> CreateDebugCallFrameInfo();
+  virtual std::unique_ptr<CompactUnwindInfo> CreateCompactUnwindInfo();
+  virtual std::unique_ptr<ArmUnwindInfo> CreateArmUnwindInfo();
+
 protected:
   // Member variables.
   FileSpec m_file;
Index: lldb/include/lldb/Symbol/ICallFrameInfo.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Symbol/ICallFrameInfo.h
@@ -0,0 +1,34 @@
+//===-- ICallFrameInfo.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ICallFrameInfo_h_
+#define liblldb_ICallFrameInfo_h_
+
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Utility/RangeMap.h"
+
+namespace lldb_private {
+
+class ICallFrameInfo {
+public:
+  virtual ~ICallFrameInfo() = default;
+
+  virtual bool GetAddressRange(Address addr, AddressRange &range) = 0;
+
+  virtual bool GetUnwindPlan(const Address &addr, UnwindPlan &unwind_plan) = 0;
+  virtual bool GetUnwindPlan(const AddressRange &range, UnwindPlan &unwind_plan) = 0;
+
+  typedef RangeVector<lldb::addr_t, uint32_t> FunctionAddressAndSizeVector;
+  virtual void GetFunctionAddressAndSizeVector(FunctionAddressAndSizeVector &function_info) = 0;
+
+  virtual void ForEachEntries(const std::function<bool(lldb::addr_t, uint32_t)> &callback) = 0;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ICallFrameInfo_h_
Index: lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
===================================================================
--- lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
+++ lldb/include/lldb/Symbol/DWARFCallFrameInfo.h
@@ -14,6 +14,7 @@
 
 #include "lldb/Core/AddressRange.h"
 #include "lldb/Core/dwarf.h"
+#include "lldb/Symbol/ICallFrameInfo.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Utility/Flags.h"
@@ -30,7 +31,7 @@
 // generate an UnwindPlan based on the FDE in the eh_frame / debug_frame
 // section.
 
-class DWARFCallFrameInfo {
+class DWARFCallFrameInfo : public virtual ICallFrameInfo {
 public:
   enum Type { EH, DWARF };
 
@@ -41,19 +42,17 @@
   // Locate an AddressRange that includes the provided Address in this object's
   // eh_frame/debug_info Returns true if a range is found to cover that
   // address.
-  bool GetAddressRange(Address addr, AddressRange &range);
+  bool GetAddressRange(Address addr, AddressRange &range) override;
 
   /// Return an UnwindPlan based on the call frame information encoded in the
   /// FDE of this DWARFCallFrameInfo section. The returned plan will be valid
   /// (at least) for the given address.
-  bool GetUnwindPlan(const Address &addr, UnwindPlan &unwind_plan);
+  bool GetUnwindPlan(const Address &addr, UnwindPlan &unwind_plan) override;
 
   /// Return an UnwindPlan based on the call frame information encoded in the
   /// FDE of this DWARFCallFrameInfo section. The returned plan will be valid
   /// (at least) for some address in the given range.
-  bool GetUnwindPlan(const AddressRange &range, UnwindPlan &unwind_plan);
-
-  typedef RangeVector<lldb::addr_t, uint32_t> FunctionAddressAndSizeVector;
+  bool GetUnwindPlan(const AddressRange &range, UnwindPlan &unwind_plan) override;
 
   // Build a vector of file address and size for all functions in this Module
   // based on the eh_frame FDE entries.
@@ -70,10 +69,9 @@
   //      is present in this Module.
 
   void
-  GetFunctionAddressAndSizeVector(FunctionAddressAndSizeVector &function_info);
+  GetFunctionAddressAndSizeVector(FunctionAddressAndSizeVector &function_info) override;
 
-  void ForEachFDEEntries(
-      const std::function<bool(lldb::addr_t, uint32_t, dw_offset_t)> &callback);
+  void ForEachEntries(const std::function<bool(lldb::addr_t, uint32_t)> &callback) override;
 
 private:
   enum { CFI_AUG_MAX_SIZE = 8, CFI_HEADER_SIZE = 8 };
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to