TCF Agent: limit ARM stack crawl to current function body if the function symbol is available
diff --git a/agent/machine/arm/tcf/stack-crawl-arm.c b/agent/machine/arm/tcf/stack-crawl-arm.c
index cd8c1cc..dfc0656 100644
--- a/agent/machine/arm/tcf/stack-crawl-arm.c
+++ b/agent/machine/arm/tcf/stack-crawl-arm.c
@@ -44,6 +44,7 @@
 #include <tcf/framework/context.h>
 #include <tcf/framework/myalloc.h>
 #include <tcf/framework/trace.h>
+#include <tcf/services/symbols.h>
 #include <tcf/services/stacktrace.h>
 #include <machine/arm/tcf/stack-crawl-arm.h>
 
@@ -2230,6 +2231,24 @@
     RegData org_4to11[8];
     RegData org_cpsr = cpsr_data;
     RegData org_spsr = spsr_data;
+    ContextAddress func_addr = 0;
+    ContextAddress func_size = 0;
+
+#if ENABLE_Symbols
+    if (reg_data[15].o) {
+        Symbol * sym = NULL;
+        int sym_class = SYM_CLASS_UNKNOWN;
+        ContextAddress sym_addr = 0;
+        ContextAddress sym_size = 0;
+        if (find_symbol_by_addr(stk_ctx, STACK_NO_FRAME, reg_data[15].v, &sym) == 0 &&
+                get_symbol_class(sym, &sym_class) == 0 && sym_class == SYM_CLASS_FUNCTION &&
+                get_symbol_size(sym, &sym_size) == 0 && sym_size != 0 &&
+                get_symbol_address(sym, &sym_addr) == 0 && sym_addr != 0) {
+            func_addr = sym_addr;
+            func_size = sym_size;
+        }
+    }
+#endif
 
     TRACE_INSTRUCTIONS_HOOK;
 
@@ -2258,6 +2277,10 @@
             else if (!cpsr_data.o) {
                 error = set_errno(ERR_OTHER, "CPSR value not available");
             }
+            else if (func_size > 0 && (reg_data[15].v < func_addr ||
+                    (func_addr + func_size > func_addr && reg_data[15].v >= func_addr + func_size))) {
+                error = set_errno(ERR_OTHER, "PC outside current function");
+            }
             else {
                 int r = 0;
                 uint32_t flag_t = 1 << 5;
@@ -2316,7 +2339,7 @@
     }
     cpsr_data.o = 0;
     spsr_data.o = 0;
-    if (org_cpsr.o && org_spsr.o && org_lr.o) {
+    if (org_cpsr.o && org_spsr.o && ((org_spsr.v & 0x1f) > 0x10) && org_lr.o) {
         cpsr_data = org_cpsr;
         spsr_data = org_spsr;
         reg_data[15] = org_lr;