================
@@ -868,6 +868,41 @@ RegisterContextUnwind::GetFullUnwindPlanForFrame() {
     return arch_default_unwind_plan_sp;
   }
 
+  // Function outlining is a clang feature where common blocks of instructions
+  // from separate functions can be put in a separate utility function, and
+  // the original functions call into the utility function to execute them,
+  // resulting in fewer bytes used for the code section overall.
+  //
+  // The call to the OUTLINED_FUNCTION may not be a normal ABI call (e.g.
+  // on RISCV it might be called `jal t0, OUTLINED_FUNCTION_<nn>` putting the
+  // return address in a temporary register instead of $ra).  Tthe unwind
+  // instructions in eh_frame/debug_frame are not correct today for an
+  // OUTLINED_FUNCTION, even when a normal ABI call is made.
+  // Clang does not insert CFI directives in the OUTLINED_FUNCTION so it
+  // will look like a frameless function that does nothing beyond its initial
+  // unwind state.
+  //
+  // A function may outline its prologue, mid-function block of instructions,
+  // or its epilogue.  If a function's prologue is outlined, the unwind
+  // instructions (eh_frame/debug_frame/lldb's instruction analysis) for the
+  // original function are incorrect and cannot be trusted.
+  //
+  // If we are in an OUTLINED_FUNCTION in a backtrace, distrust all sources
+  // of unwind information and use the architectural default unwind plan
+  // instead.  We may miss the caller stack frame in the backtrace, but it
+  // will work more reliably than any other method.
+  if (m_sym_ctx_valid && arch_default_unwind_plan_sp) {
+    const char *name = GetSymbolOrFunctionName(m_sym_ctx).AsCString("");
+    if (!strncmp(name, "OUTLINED_FUNCTION_",
+                 sizeof("OUTLINED_FUNCTION_") - 1)) {
----------------
jasonmolenda wrote:

clang has a separate process where rarely-executed parts of a function can be 
split apart into a `<funcname>.cold.<n>` separate function, I think that is for 
keeping cache locality for code though.  Those .cold. functions are usually for 
crashing the program because something was invalid IME.

The problem with the OUTLINED_FUNCTION DWARF debug_frame is that it has the 
initial default unwind state for an ABI call (e.g. aarch64 `pc=$lr`) that is 
either incomplete or wrong (when the return address register is a different 
reg).  But also, a full unwind plan can come from lldb's instruction emulation 
engine, and it will also produce incorrect results because this outlined 
function may have been called in a non-ABI-compliant way.

https://github.com/llvm/llvm-project/pull/204500
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to