about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2022-12-15 20:52:55 +0000
committerEric Wong <mwrap-perl@80x24.org>2022-12-16 09:27:49 +0000
commit52d13d89eaedac53c32109b73af86d6d1f69eda3 (patch)
tree212f3a26fe0d89b25fbaf8757e765b2bd6290b74
parent000f631f8096d8140135eca0daef8c622f89177a (diff)
downloadmwrap-52d13d89eaedac53c32109b73af86d6d1f69eda3.tar.gz
Compilers don't like seeing `sl.bt[-1]', so we give backtrace(3)
the same address by another means.  We'll also save allocating
one pointer off the stack by capping the union padding.
-rw-r--r--mwrap_core.h23
1 files changed, 21 insertions, 2 deletions
diff --git a/mwrap_core.h b/mwrap_core.h
index 1b3d98f..3fd67f1 100644
--- a/mwrap_core.h
+++ b/mwrap_core.h
@@ -134,6 +134,7 @@ static void *my_mempcpy(void *dest, const void *src, size_t n)
 #define RETURN_ADDRESS(nr) \
   __builtin_extract_return_addr(__builtin_return_address(nr))
 
+
 #define SRC_LOC_BT(bt) union stk_bt bt; do { \
         uint32_t depth = locating ? 1 : bt_req_depth; \
         switch (depth) { \
@@ -142,7 +143,7 @@ static void *my_mempcpy(void *dest, const void *src, size_t n)
         default: /* skip 1st level of BT since thats our function */ \
                 mwrap_assert(bt_req_depth <= MWRAP_BT_MAX); \
                 ++locating; \
-                long n = (long)backtrace(&bt.sl.bt[-1], bt_req_depth); \
+                long n = (long)backtrace(bt_dst(&bt), bt_req_depth); \
                 --locating; \
                 bt.sl.bt_len = n <= 1 ? 0 : (uint32_t)n - 1; \
                 if (n > 1) mwrap_assert(bt.sl.bt[0] == RETURN_ADDRESS(0)); \
@@ -209,9 +210,27 @@ union stk_sf {
 
 union stk_bt {
         struct src_loc sl;
-        char buf_[sizeof(struct src_loc) + sizeof(void *) * MWRAP_BT_MAX];
+        /* we subtract one level from MWRAP_BT_MAX since we discard one
+         * level of backtrace(3) (see below for why) */
+        char buf_[sizeof(struct src_loc) + sizeof(void *) * (MWRAP_BT_MAX-1)];
 };
 
+/*
+ * we discard the 1st-level of the backtrace(3) since it's our *alloc
+ * function (and therefore uninteresting), so we want backtrace(3) to
+ * write to bt->sl.bt[-1] so that bt->sl.bt[0] is the first interesting
+ * thing.
+ */
+#ifdef static_assert
+static_assert(offsetof(struct src_loc, lineno) + sizeof(void *) ==
+                offsetof(struct src_loc, bt),
+                "bt lineno is is bt[-1]");
+#endif
+static void **bt_dst(union stk_bt *bt)
+{
+        return (void **)&bt->sl.lineno;
+}
+
 static struct alloc_hdr *ptr2hdr(void *p)
 {
         return (struct alloc_hdr *)((uintptr_t)p - sizeof(struct alloc_hdr));