Loading...
--- /dev/null
+++ libmalloc/libmalloc-657.80.3/src/stack_trace.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "stack_trace.h"
+
+#include <TargetConditionals.h>
+#include <execinfo.h>
+
+
+// Note: Shifts on signed types are a minefield. Avoid doing it!
+
+static uintptr_t
+zigzag_encode(uintptr_t val)
+{
+ uintptr_t x = val << 1;
+ return ((intptr_t)val < 0) ? ~x : x;
+}
+
+static uintptr_t
+zigzag_decode(uintptr_t encoded_val)
+{
+ uintptr_t x = encoded_val >> 1;
+ return (encoded_val & 1) ? ~x : x;
+}
+
+static uintptr_t
+codeoffset_encode(intptr_t val)
+{
+ intptr_t x = val;
+ if (TARGET_CPU_ARM64) x /= 4; // instructions are 4 byte-aligned
+ return zigzag_encode(x);
+}
+
+static intptr_t
+codeoffset_decode(uintptr_t encoded_val)
+{
+ intptr_t x = zigzag_decode(encoded_val);
+ if (TARGET_CPU_ARM64) x *= 4; // instructions are 4 byte-aligned
+ return x;
+}
+
+const static uintptr_t k_shift = 7;
+const static uintptr_t k_stop_bit = 1 << k_shift;
+const static uintptr_t k_data_bits = ~k_stop_bit;
+
+static size_t
+varint_encode(uint8_t *buffer, size_t size, uintptr_t val)
+{
+ uintptr_t x = val;
+ size_t len = 0;
+ do {
+ if (len == size) {
+ return 0;
+ }
+ buffer[len] = x & k_data_bits;
+ x >>= k_shift;
+ len++;
+ } while (x);
+
+ buffer[len - 1] |= k_stop_bit;
+ return len;
+}
+
+static size_t
+varint_decode(const uint8_t *buffer, size_t size, uintptr_t *val)
+{
+ uintptr_t x = 0;
+ size_t len = 0;
+ do {
+ if (len == size) {
+ return 0;
+ }
+ uintptr_t bits = buffer[len] & k_data_bits;
+ x |= bits << (len * k_shift);
+ len++;
+ } while (!(buffer[len - 1] & k_stop_bit));
+
+ *val = x;
+ return len;
+}
+
+static size_t
+trace_encode(uint8_t *buffer, size_t size, const vm_address_t *addrs, uint32_t num_addrs)
+{
+ size_t used = 0;
+ for (uint32_t i = 0; i < num_addrs; i++) {
+ intptr_t offset = addrs[i] - (i > 0 ? addrs[i - 1] : 0);
+ uintptr_t encoded_offset = codeoffset_encode(offset);
+ size_t len = varint_encode(&buffer[used], size - used, encoded_offset);
+ if (len == 0) {
+ break;
+ }
+ used += len;
+ }
+
+ return used;
+}
+
+uint32_t
+trace_decode(const uint8_t *buffer, size_t size, vm_address_t *addrs, uint32_t num_addrs)
+{
+ size_t used = 0;
+ uint32_t i;
+ for (i = 0; i < num_addrs; i++) {
+ uintptr_t encoded_offset;
+ size_t len = varint_decode(&buffer[used], size - used, &encoded_offset);
+ if (len == 0) {
+ break;
+ }
+ used += len;
+
+ intptr_t offset = codeoffset_decode(encoded_offset);
+ addrs[i] = offset + (i > 0 ? addrs[i - 1] : 0);
+ }
+
+ return i;
+}
+
+MALLOC_NOINLINE
+size_t
+trace_collect(uint8_t *buffer, size_t size)
+{
+ // frame 0: this function (no inline)
+ const uint32_t dropped_frames = 1;
+ const uint32_t good_frames = 64;
+ const uint32_t max_frames = good_frames + dropped_frames;
+ vm_address_t frames[max_frames];
+
+ uint32_t num_frames = backtrace((void **)frames, max_frames);
+ if (num_frames <= dropped_frames) {
+ return 0;
+ }
+
+ uint32_t num_addrs = num_frames - dropped_frames;
+ return trace_encode(buffer, size, &frames[1], num_addrs);
+}