From: Olivier Dion Date: Wed, 22 Feb 2023 20:19:14 +0000 (-0500) Subject: Fix: adding a user space probe fails on thumb functions X-Git-Tag: v2.12.14~2 X-Git-Url: https://git.liburcu.org/?a=commitdiff_plain;ds=sidebyside;h=fd44f4931371da6a4a995f1d0298030d65d3aeb6;p=lttng-tools.git Fix: adding a user space probe fails on thumb functions 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. 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. We were not masking the thumb bit, thus using the wrong address offset by one. Change-Id: Iaff8ccea3a319f9d9ad80501f1beccd74d1ef56d Signed-off-by: Olivier Dion Signed-off-by: Jérémie Galarneau --- diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 1839256ac..d8613deac 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -48,6 +48,30 @@ static int kernel_tracer_fd = -1; #include #include +/* + * 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. * @@ -400,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 " @@ -428,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 "