Add a new Row setting to mark all un-declared regs as Undefined

Add a new state for UnwindPlan::Row which indicates that any
register not listed is not defined, and should not be found in
stack frames newer than this one and passed up the stack.  Mostly
intended for use with architectural default unwind plans that are
used for jitted stack frames, where we have no unwind information
or start address.  lldb has no way to tell if registers were
spilled in the jitted frame & overwritten, so passing register
values up the stack is not safe to show the user.

Architectural default unwind plans are also used as a fast unwind
plan on x86_64 in particular, and are used as the fallback unwind
plans when lldb thinks it may be able to work around a problem
which causes the unwinder to stop walking the stack early.

For fast unwind plans, when we don't find a register location in
the arch default unwind plan, we fall back to computing & using
the full unwind plan. One small part of this patch is to know that
a register marked as Undefined in the fast unwind plan is a special
case, and we should continue on to the full unwind plan to find what
the real unwind rule is for this register.

Differential Revision: https://reviews.llvm.org/D96829
<rdar://problem/70398009>

GitOrigin-RevId: fcdef15d77bde8a200cd28242077cd2496f138a4
diff --git a/include/lldb/Symbol/UnwindPlan.h b/include/lldb/Symbol/UnwindPlan.h
index 40814da..06c76ca 100644
--- a/include/lldb/Symbol/UnwindPlan.h
+++ b/include/lldb/Symbol/UnwindPlan.h
@@ -360,6 +360,25 @@
 
     bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace);
 
+    // When this UnspecifiedRegistersAreUndefined mode is
+    // set, any register that is not specified by this Row will
+    // be described as Undefined.
+    // This will prevent the unwinder from iterating down the
+    // stack looking for a spill location, or a live register value
+    // at frame 0.
+    // It would be used for an UnwindPlan row where we can't track
+    // spilled registers -- for instance a jitted stack frame where
+    // we have no unwind information or start address -- and registers
+    // MAY have been spilled and overwritten, so providing the
+    // spilled/live value from a newer frame may show an incorrect value.
+    void SetUnspecifiedRegistersAreUndefined(bool unspec_is_undef) {
+      m_unspecified_registers_are_undefined = unspec_is_undef;
+    }
+
+    bool GetUnspecifiedRegistersAreUndefined() {
+      return m_unspecified_registers_are_undefined;
+    }
+
     void Clear();
 
     void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread,
@@ -372,6 +391,7 @@
     FAValue m_cfa_value;
     FAValue m_afa_value;
     collection m_register_locations;
+    bool m_unspecified_registers_are_undefined;
   }; // class Row
 
   typedef std::shared_ptr<Row> RowSP;
diff --git a/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
index ea0c09a..861310e 100644
--- a/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
+++ b/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
@@ -384,6 +384,7 @@
 
   row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
   row->SetOffset(0);
+  row->SetUnspecifiedRegistersAreUndefined(true);
 
   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
index 5918e2c..0f74c1f 100644
--- a/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
+++ b/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
@@ -356,6 +356,7 @@
 
   row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
   row->SetOffset(0);
+  row->SetUnspecifiedRegistersAreUndefined(true);
 
   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp b/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp
index 06c4590..e429f3e 100644
--- a/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp
+++ b/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp
@@ -1824,6 +1824,7 @@
 
   row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
   row->SetOffset(0);
+  row->SetUnspecifiedRegistersAreUndefined(true);
 
   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/source/Plugins/ABI/ARM/ABISysV_arm.cpp b/source/Plugins/ABI/ARM/ABISysV_arm.cpp
index 26b3152..8a9be3f 100644
--- a/source/Plugins/ABI/ARM/ABISysV_arm.cpp
+++ b/source/Plugins/ABI/ARM/ABISysV_arm.cpp
@@ -1940,6 +1940,7 @@
 
   row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
   row->SetOffset(0);
+  row->SetUnspecifiedRegistersAreUndefined(true);
 
   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
index 47aaefd..6794f7d 100644
--- a/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
+++ b/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
@@ -1225,6 +1225,7 @@
 
   UnwindPlan::RowSP row(new UnwindPlan::Row);
 
+  row->SetUnspecifiedRegistersAreUndefined(true);
   row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_FP, 8);
 
   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, -8, true);
diff --git a/source/Plugins/ABI/Mips/ABISysV_mips.cpp b/source/Plugins/ABI/Mips/ABISysV_mips.cpp
index d66e092..538ec06 100644
--- a/source/Plugins/ABI/Mips/ABISysV_mips.cpp
+++ b/source/Plugins/ABI/Mips/ABISysV_mips.cpp
@@ -985,6 +985,7 @@
 
   UnwindPlan::RowSP row(new UnwindPlan::Row);
 
+  row->SetUnspecifiedRegistersAreUndefined(true);
   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
 
   row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
diff --git a/source/Plugins/ABI/Mips/ABISysV_mips64.cpp b/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
index 5e72af0..7220508 100644
--- a/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
+++ b/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
@@ -1156,6 +1156,7 @@
 
   UnwindPlan::RowSP row(new UnwindPlan::Row);
 
+  row->SetUnspecifiedRegistersAreUndefined(true);
   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
 
   row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
diff --git a/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp b/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
index d560564..cfecf35 100644
--- a/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
+++ b/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
@@ -900,6 +900,7 @@
   UnwindPlan::RowSP row(new UnwindPlan::Row);
 
   const int32_t ptr_size = 4;
+  row->SetUnspecifiedRegistersAreUndefined(true);
   row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);
 
   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 1, true);
diff --git a/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp
index 6031431..7cc9482 100644
--- a/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp
+++ b/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp
@@ -1003,6 +1003,7 @@
 
   UnwindPlan::RowSP row(new UnwindPlan::Row);
   const int32_t ptr_size = 8;
+  row->SetUnspecifiedRegistersAreUndefined(true);
   row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);
 
   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
diff --git a/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp b/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp
index 89112de..461e4af 100644
--- a/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp
+++ b/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp
@@ -389,6 +389,7 @@
 
   row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
   row->SetOffset(0);
+  row->SetUnspecifiedRegistersAreUndefined(true);
 
   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/source/Plugins/ABI/X86/ABISysV_i386.cpp b/source/Plugins/ABI/X86/ABISysV_i386.cpp
index 38d7364..7d2f0a6 100644
--- a/source/Plugins/ABI/X86/ABISysV_i386.cpp
+++ b/source/Plugins/ABI/X86/ABISysV_i386.cpp
@@ -652,6 +652,7 @@
 
   row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
   row->SetOffset(0);
+  row->SetUnspecifiedRegistersAreUndefined(true);
 
   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/source/Plugins/ABI/X86/ABISysV_x86_64.cpp b/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
index 8d56147..196b45b 100644
--- a/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
+++ b/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
@@ -887,6 +887,7 @@
   const int32_t ptr_size = 8;
   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);
   row->SetOffset(0);
+  row->SetUnspecifiedRegistersAreUndefined(true);
 
   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp b/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
index da24145..6c473c6 100644
--- a/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
+++ b/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
@@ -767,6 +767,7 @@
   const int32_t ptr_size = 8;
   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);
   row->SetOffset(0);
+  row->SetUnspecifiedRegistersAreUndefined(true);
 
   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/source/Symbol/UnwindPlan.cpp b/source/Symbol/UnwindPlan.cpp
index d24cabe..d74c78f 100644
--- a/source/Symbol/UnwindPlan.cpp
+++ b/source/Symbol/UnwindPlan.cpp
@@ -217,6 +217,7 @@
   m_cfa_value.SetUnspecified();
   m_afa_value.SetUnspecified();
   m_offset = 0;
+  m_unspecified_registers_are_undefined = false;
   m_register_locations.clear();
 }
 
@@ -242,11 +243,11 @@
     idx->second.Dump(s, unwind_plan, this, thread, verbose);
     s.PutChar(' ');
   }
-  s.EOL();
 }
 
 UnwindPlan::Row::Row()
-    : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations() {}
+    : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations(),
+      m_unspecified_registers_are_undefined(false) {}
 
 bool UnwindPlan::Row::GetRegisterInfo(
     uint32_t reg_num,
@@ -256,6 +257,10 @@
     register_location = pos->second;
     return true;
   }
+  if (m_unspecified_registers_are_undefined) {
+    register_location.SetUndefined();
+    return true;
+  }
   return false;
 }
 
@@ -348,10 +353,11 @@
 }
 
 bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const {
-  return m_offset == rhs.m_offset &&
-      m_cfa_value == rhs.m_cfa_value &&
-      m_afa_value == rhs.m_afa_value &&
-      m_register_locations == rhs.m_register_locations;
+  return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value &&
+         m_afa_value == rhs.m_afa_value &&
+         m_unspecified_registers_are_undefined ==
+             rhs.m_unspecified_registers_are_undefined &&
+         m_register_locations == rhs.m_register_locations;
 }
 
 void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) {
@@ -552,6 +558,7 @@
   for (pos = begin; pos != end; ++pos) {
     s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos));
     (*pos)->Dump(s, this, thread, base_addr);
+    s.Printf("\n");
   }
 }
 
diff --git a/source/Target/RegisterContextUnwind.cpp b/source/Target/RegisterContextUnwind.cpp
index 991a3c8..a677121 100644
--- a/source/Target/RegisterContextUnwind.cpp
+++ b/source/Target/RegisterContextUnwind.cpp
@@ -542,6 +542,8 @@
       StreamString active_row_strm;
       active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread,
                        m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+      UnwindLogMsg("Using fast unwind plan '%s'",
+                   m_fast_unwind_plan_sp->GetSourceName().AsCString());
       UnwindLogMsg("active row: %s", active_row_strm.GetData());
     }
   } else {
@@ -556,6 +558,8 @@
         active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(),
                          &m_thread,
                          m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+        UnwindLogMsg("Using full unwind plan '%s'",
+                     m_full_unwind_plan_sp->GetSourceName().AsCString());
         UnwindLogMsg("active row: %s", active_row_strm.GetData());
       }
     }
@@ -662,13 +666,6 @@
       *m_thread.CalculateTarget(), m_thread);
   if (unwind_plan_sp) {
     if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
-      Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
-      if (log && log->GetVerbose()) {
-        if (m_fast_unwind_plan_sp)
-          UnwindLogMsgVerbose("frame, and has a fast UnwindPlan");
-        else
-          UnwindLogMsgVerbose("frame");
-      }
       m_frame_type = eNormalFrame;
       return unwind_plan_sp;
     } else {
@@ -1147,6 +1144,7 @@
 RegisterContextUnwind::SavedLocationForRegister(
     uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc) {
   RegisterNumber regnum(m_thread, eRegisterKindLLDB, lldb_regnum);
+  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
 
   // Have we already found this register location?
   if (!m_registers.empty()) {
@@ -1179,8 +1177,17 @@
                    (int)unwindplan_registerkind);
       return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
     }
+    // The architecture default unwind plan marks unknown registers as
+    // Undefined so that we don't forward them up the stack when a
+    // jitted stack frame may have overwritten them.  But when the
+    // arch default unwind plan is used as the Fast Unwind Plan, we
+    // need to recognize this & switch over to the Full Unwind Plan
+    // to see what unwind rule that (more knoweldgeable, probably)
+    // UnwindPlan has.  If the full UnwindPlan says the register 
+    // location is Undefined, then it really is.
     if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind),
-                                    unwindplan_regloc)) {
+                                    unwindplan_regloc) &&
+        !unwindplan_regloc.IsUndefined()) {
       UnwindLogMsg(
           "supplying caller's saved %s (%d)'s location using FastUnwindPlan",
           regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
@@ -1191,8 +1198,11 @@
   if (!have_unwindplan_regloc) {
     // m_full_unwind_plan_sp being NULL means that we haven't tried to find a
     // full UnwindPlan yet
-    if (!m_full_unwind_plan_sp)
+    bool got_new_full_unwindplan = false;
+    if (!m_full_unwind_plan_sp) {
       m_full_unwind_plan_sp = GetFullUnwindPlanForFrame();
+      got_new_full_unwindplan = true;
+    }
 
     if (m_full_unwind_plan_sp) {
       RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric,
@@ -1202,6 +1212,16 @@
           m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
       unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind();
 
+      if (got_new_full_unwindplan && active_row.get() && log) {
+        StreamString active_row_strm;
+        ExecutionContext exe_ctx(m_thread.shared_from_this());
+        active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(),
+                         &m_thread,
+                         m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+        UnwindLogMsg("Using full unwind plan '%s'",
+                     m_full_unwind_plan_sp->GetSourceName().AsCString());
+        UnwindLogMsg("active row: %s", active_row_strm.GetData());
+      }
       RegisterNumber return_address_reg;
 
       // If we're fetching the saved pc and this UnwindPlan defines a