diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -614,6 +614,26 @@
           m_curr_row->SetRegisterLocationToSame(reg_num,
                                                 false /*must_replace*/);
           m_curr_row_modified = true;
+
+          // FP has been restored to its original value, we are back
+          // to using SP to calculate the CFA.
+          if (m_fp_is_cfa) {
+            m_fp_is_cfa = false;
+            RegisterInfo sp_reg_info;
+            lldb::RegisterKind sp_reg_kind = eRegisterKindGeneric;
+            uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+            m_inst_emulator_up->GetRegisterInfo(sp_reg_kind, sp_reg_num,
+                                                sp_reg_info);
+            RegisterValue sp_reg_val;
+            if (GetRegisterValue(sp_reg_info, sp_reg_val)) {
+              m_cfa_reg_info = sp_reg_info;
+              const uint32_t cfa_reg_num =
+                  sp_reg_info.kinds[m_unwind_plan_ptr->GetRegisterKind()];
+              assert(cfa_reg_num != LLDB_INVALID_REGNUM);
+              m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
+                  cfa_reg_num, m_initial_sp - sp_reg_val.GetAsUInt64());
+            }
+          }
         }
         break;
       case EmulateInstruction::eInfoTypeISA:
diff --git a/lldb/test/API/symbol_ondemand/shared_library/TestSharedLib.py b/lldb/test/API/symbol_ondemand/shared_library/TestSharedLib.py
deleted file mode 100644
--- a/lldb/test/API/symbol_ondemand/shared_library/TestSharedLib.py
+++ /dev/null
@@ -1,157 +0,0 @@
-"""Test that types defined in shared libraries work correctly."""
-
-
-import lldb
-import unittest2
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-import lldbsuite.test.lldbutil as lldbutil
-
-
-class SharedLibTestCase(TestBase):
-
-    mydir = TestBase.compute_mydir(__file__)
-
-    def setUp(self):
-        # Call super's setUp().
-        TestBase.setUp(self)
-        # Find the line number to break inside main().
-        self.source = "shared.c"
-        self.line = line_number(self.source, "// Set breakpoint 0 here.")
-        self.shlib_names = ["foo"]
-
-    def common_setup(self):
-        # Run in synchronous mode
-        self.dbg.SetAsync(False)
-        self.runCmd("settings set symbols.load-on-demand true")
-
-        # Create a target by the debugger.
-        self.target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
-        self.assertTrue(self.target, VALID_TARGET)
-
-        # Register our shared libraries for remote targets so they get
-        # automatically uploaded
-        self.environment = self.registerSharedLibrariesWithTarget(
-            self.target, self.shlib_names
-        )
-
-        ctx = self.platformContext
-        self.shared_lib_name = ctx.shlib_prefix + "foo." + ctx.shlib_extension
-
-    def test_source_line_breakpoint(self):
-        self.build()
-        self.common_setup()
-
-        lldbutil.run_break_set_by_file_and_line(
-            self, "foo.c", 4, num_expected_locations=1, loc_exact=True
-        )
-
-        # Now launch the process, and do not stop at entry point.
-        process = self.target.LaunchSimple(
-            None, self.environment, self.get_process_working_directory()
-        )
-        self.assertTrue(process, PROCESS_IS_VALID)
-
-        # The stop reason of the thread should be breakpoint.
-        self.expect(
-            "thread list",
-            STOPPED_DUE_TO_BREAKPOINT,
-            substrs=["stopped", "stop reason = breakpoint"],
-        )
-        # The breakpoint should have a hit count of 1.
-        lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=1)
-
-        thread = process.GetSelectedThread()
-        stack_frames = lldbutil.get_stack_frames(thread)
-        self.assertGreater(len(stack_frames), 2)
-
-        leaf_frame = stack_frames[0]
-        self.assertEqual("foo.c", leaf_frame.GetLineEntry().GetFileSpec().GetFilename())
-        self.assertEqual(4, leaf_frame.GetLineEntry().GetLine())
-
-        parent_frame = stack_frames[1]
-        self.assertEqual(
-            "shared.c", parent_frame.GetLineEntry().GetFileSpec().GetFilename()
-        )
-        self.assertEqual(7, parent_frame.GetLineEntry().GetLine())
-
-    def test_symbolic_breakpoint(self):
-        self.build()
-        self.common_setup()
-
-        lldbutil.run_break_set_by_symbol(
-            self, "foo", sym_exact=True, num_expected_locations=1
-        )
-
-        # Now launch the process, and do not stop at entry point.
-        process = self.target.LaunchSimple(
-            None, self.environment, self.get_process_working_directory()
-        )
-        self.assertTrue(process, PROCESS_IS_VALID)
-
-        # The stop reason of the thread should be breakpoint.
-        self.expect(
-            "thread list",
-            STOPPED_DUE_TO_BREAKPOINT,
-            substrs=["stopped", "stop reason = breakpoint"],
-        )
-        # The breakpoint should have a hit count of 1.
-        lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=1)
-
-        thread = process.GetSelectedThread()
-        stack_frames = lldbutil.get_stack_frames(thread)
-        self.assertGreater(len(stack_frames), 2)
-
-        leaf_frame = stack_frames[0]
-        self.assertEqual("foo.c", leaf_frame.GetLineEntry().GetFileSpec().GetFilename())
-        self.assertEqual(4, leaf_frame.GetLineEntry().GetLine())
-
-        parent_frame = stack_frames[1]
-        self.assertEqual(
-            "shared.c", parent_frame.GetLineEntry().GetFileSpec().GetFilename()
-        )
-        self.assertEqual(7, parent_frame.GetLineEntry().GetLine())
-
-    def test_global_variable_hydration(self):
-        self.build()
-        self.common_setup()
-
-        lldbutil.run_break_set_by_file_and_line(
-            self, self.source, self.line, num_expected_locations=1, loc_exact=True
-        )
-
-        # Now launch the process, and do not stop at entry point.
-        process = self.target.LaunchSimple(
-            None, self.environment, self.get_process_working_directory()
-        )
-        self.assertTrue(process, PROCESS_IS_VALID)
-
-        # The stop reason of the thread should be breakpoint.
-        self.expect(
-            "thread list",
-            STOPPED_DUE_TO_BREAKPOINT,
-            substrs=["stopped", "stop reason = breakpoint"],
-        )
-
-        # The breakpoint should have a hit count of 1.
-        lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=1)
-
-        self.expect(
-            "target variable --shlib a.out",
-            "Breakpoint in a.out should have hydrated the debug info",
-            substrs=["global_shared = 897"],
-        )
-
-        self.expect(
-            "target variable --shlib " + self.shared_lib_name,
-            "shared library should not have debug info by default",
-            matching=False,
-            substrs=["global_foo"],
-        )
-
-        self.expect(
-            "target variable global_foo --shlib " + self.shared_lib_name,
-            "Match global_foo in symbol table should hydrate debug info",
-            matching=True,
-            substrs=["global_foo = 321"],
-        )
diff --git a/lldb/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp b/lldb/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp
--- a/lldb/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp
+++ b/lldb/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp
@@ -778,3 +778,65 @@
   EXPECT_EQ(32, row_sp->GetCFAValue().GetOffset());
 }
 
+TEST_F(TestArm64InstEmulation, TestCFAResetToSP) {
+  ArchSpec arch("arm64-apple-ios15");
+  std::unique_ptr<UnwindAssemblyInstEmulation> engine(
+      static_cast<UnwindAssemblyInstEmulation *>(
+          UnwindAssemblyInstEmulation::CreateInstance(arch)));
+  ASSERT_NE(nullptr, engine);
+
+  UnwindPlan::RowSP row_sp;
+  AddressRange sample_range;
+  UnwindPlan unwind_plan(eRegisterKindLLDB);
+  UnwindPlan::Row::RegisterLocation regloc;
+
+  // The called_from_nodebug() from TestStepNoDebug.py
+  // Most of the previous unit tests have $sp being set as
+  // $fp plus an offset, and the unwinder recognizes that
+  // as a CFA change.  This codegen overwrites $fp and we
+  // need to know that CFA is now in terms of $sp.
+  uint8_t data[] = {
+      // prologue
+      0xff, 0x83, 0x00, 0xd1, //  0: 0xd10083ff sub sp, sp, #0x20
+      0xfd, 0x7b, 0x01, 0xa9, //  4: 0xa9017bfd stp x29, x30, [sp, #0x10]
+      0xfd, 0x43, 0x00, 0x91, //  8: 0x910043fd add x29, sp, #0x10
+
+      // epilogue
+      0xfd, 0x7b, 0x41, 0xa9, // 12: 0xa9417bfd ldp x29, x30, [sp, #0x10]
+      0xff, 0x83, 0x00, 0x91, // 16: 0x910083ff add sp, sp, #0x20
+      0xc0, 0x03, 0x5f, 0xd6, // 20: 0xd65f03c0 ret
+  };
+
+  // UnwindPlan we expect:
+  // row[0]:    0: CFA=sp +0 =>
+  // row[1]:    4: CFA=sp+32 =>
+  // row[2]:    8: CFA=sp+32 => fp=[CFA-16] lr=[CFA-8]
+  // row[3]:   12: CFA=fp+16 => fp=[CFA-16] lr=[CFA-8]
+  // row[4]:   16: CFA=sp+32 => x0= <same> fp= <same> lr= <same>
+  // row[5]:   20: CFA=sp +0 => x0= <same> fp= <same> lr= <same>
+
+  // The specific issue we're testing for is after the
+  // ldp x29, x30, [sp, #0x10]
+  // when $fp and $lr have been restored to the original values,
+  // the CFA is now set in terms of the stack pointer.  If it is
+  // left as being in terms of the frame pointer, $fp now has the
+  // caller function's $fp value and our StackID will be wrong etc.
+
+  sample_range = AddressRange(0x1000, sizeof(data));
+
+  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
+      sample_range, data, sizeof(data), unwind_plan));
+
+  // Confirm CFA before epilogue instructions is in terms of $fp
+  row_sp = unwind_plan.GetRowForFunctionOffset(12);
+  EXPECT_EQ(12ull, row_sp->GetOffset());
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+
+  // Confirm that after restoring $fp to caller's value, CFA is now in
+  // terms of $sp
+  row_sp = unwind_plan.GetRowForFunctionOffset(16);
+  EXPECT_EQ(16ull, row_sp->GetOffset());
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+}