]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kperf/callstack.c
xnu-6153.121.1.tar.gz
[apple/xnu.git] / osfmk / kperf / callstack.c
index 4a38dd7c581523f94daa101d14397c91246ddaab..b42389c91164f43ebe8b4602f15eff014b5508a9 100644 (file)
@@ -335,24 +335,30 @@ kperf_ucallstack_sample(struct kp_ucallstack *cs, struct kperf_context *context)
 
        bool user64 = false;
        bool trunc = false;
-       int err = backtrace_thread_user(thread, cs->kpuc_frames,
-           cs->kpuc_nframes - 1, &cs->kpuc_nframes, &user64, &trunc);
-       cs->kpuc_flags = CALLSTACK_KERNEL_WORDS;
-       if (user64) {
-               cs->kpuc_flags |= CALLSTACK_64BIT;
-       }
-       if (trunc) {
-               cs->kpuc_flags |= CALLSTACK_TRUNCATED;
-       }
+       int error = 0;
+       /*
+        * Leave space for the fixup information.
+        */
+       unsigned int maxnframes = cs->kpuc_nframes - 1;
+       unsigned int nframes = backtrace_thread_user(thread, cs->kpuc_frames,
+           maxnframes, &error, &user64, &trunc);
+       cs->kpuc_nframes = MIN(maxnframes, nframes);
 
-       if (!err || err == EFAULT) {
+       /*
+        * Ignore EFAULT to get as much of the stack as possible.  It will be
+        * marked as truncated, below.
+        */
+       if (error == 0 || error == EFAULT) {
                callstack_fixup_user(cs, thread);
                cs->kpuc_flags |= CALLSTACK_VALID;
        } else {
                cs->kpuc_nframes = 0;
-               BUF_INFO(PERF_CS_ERROR, ERR_GETSTACK, err);
+               BUF_INFO(PERF_CS_ERROR, ERR_GETSTACK, error);
        }
 
+       cs->kpuc_flags |= CALLSTACK_KERNEL_WORDS | (user64 ? CALLSTACK_64BIT : 0) |
+           (trunc ? CALLSTACK_TRUNCATED : 0);
+
        BUF_INFO(PERF_CS_USAMPLE | DBG_FUNC_END, (uintptr_t)thread_tid(thread),
            cs->kpuc_flags, cs->kpuc_nframes);
 }