Fix: adding a user space probe fails on thumb functions
[lttng-tools.git] / src / bin / lttng-sessiond / kernel.c
index 53efad5e79ed0b60dbff2d8d3d9b04319ed12e25..d8613deaca3bca892e389cbfa12b81fe480c0275 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 EfficiOS Inc.
  *
  * SPDX-License-Identifier: GPL-2.0-only
  *
@@ -8,6 +8,7 @@
 #include "bin/lttng-sessiond/tracker.h"
 #include "common/tracker.h"
 #include "common/utils.h"
+#include "lttng/event.h"
 #include "lttng/lttng-error.h"
 #include "lttng/tracker.h"
 #define _LGPL_SOURCE
@@ -47,6 +48,30 @@ static int kernel_tracer_fd = -1;
 
 #include <lttng/userspace-probe.h>
 #include <lttng/userspace-probe-internal.h>
+/*
+ * On some architectures, calling convention details are embedded in the symbol
+ * addresses. Uprobe requires a "clean" symbol offset (or at least, an address
+ * where an instruction boundary would be legal) to add
+ * instrumentation. sanitize_uprobe_offset implements that sanitization logic on
+ * a per-architecture basis.
+ */
+#if defined(__arm__) || defined(__aarch64__)
+static inline uint64_t sanitize_uprobe_offset(uint64_t raw_offset)
+{
+       /*
+        * The least significant bit is used when branching to switch to thumb
+        * ISA. However, it's an invalid address for us; mask the least
+        * significant bit.
+        */
+       return raw_offset &= ~0b1;
+}
+#else /* defined(__arm__) || defined(__aarch64__) */
+static inline uint64_t sanitize_uprobe_offset(uint64_t raw_offset)
+{
+       return raw_offset;
+}
+#endif
+
 /*
  * Add context on a kernel channel.
  *
@@ -399,7 +424,7 @@ int userspace_probe_add_callsites(struct lttng_event *ev,
                        goto end;
                }
 
-               callsite.u.uprobe.offset = offset;
+               callsite.u.uprobe.offset = sanitize_uprobe_offset(offset);
                ret = kernctl_add_callsite(fd, &callsite);
                if (ret) {
                        WARN("Adding callsite to userspace probe "
@@ -427,7 +452,7 @@ int userspace_probe_add_callsites(struct lttng_event *ev,
                        goto end;
                }
                for (i = 0; i < offsets_count; i++) {
-                       callsite.u.uprobe.offset = offsets[i];
+                       callsite.u.uprobe.offset = sanitize_uprobe_offset(offsets[i]);
                        ret = kernctl_add_callsite(fd, &callsite);
                        if (ret) {
                                WARN("Adding callsite to userspace probe "
@@ -654,14 +679,8 @@ int kernel_disable_event(struct ltt_kernel_event *event)
 
        ret = kernctl_disable(event->fd);
        if (ret < 0) {
-               switch (-ret) {
-               case EEXIST:
-                       ret = LTTNG_ERR_KERN_EVENT_EXIST;
-                       break;
-               default:
-                       PERROR("disable kernel event");
-                       break;
-               }
+               PERROR("Failed to disable kernel event: name = '%s', fd = %d",
+                               event->event->name, event->fd);
                goto error;
        }
 
@@ -1561,7 +1580,7 @@ enum lttng_error_code kernel_snapshot_record(
        }
 
        trace_path = setup_channel_trace_path(ksess->consumer,
-                       DEFAULT_KERNEL_TRACE_DIR, &consumer_path_offset);
+                       "", &consumer_path_offset);
        if (!trace_path) {
                status = LTTNG_ERR_INVALID;
                goto error;
This page took 0.031476 seconds and 4 git commands to generate.