From 36fdcbb47cd005edd929417360ea94b1e2cf0d9e Mon Sep 17 00:00:00 2001 From: Olivier Dion Date: Wed, 22 Feb 2023 15:19:14 -0500 Subject: [PATCH] Fix: adding a user space probe fails on thumb functions MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- src/bin/lttng-sessiond/kernel.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index bdf94f1d7..4c5227189 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -62,6 +62,30 @@ static int kernel_tracer_event_notifier_group_fd = -1; static int kernel_tracer_event_notifier_group_notification_fd = -1; static struct cds_lfht *kernel_token_to_event_notifier_rule_ht; +/* + * 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. * @@ -446,7 +470,7 @@ int userspace_probe_add_callsite( goto end; } - callsite.u.uprobe.offset = offset; + callsite.u.uprobe.offset = sanitize_uprobe_offset(offset); ret = kernctl_add_callsite(fd, &callsite); if (ret) { WARN("Failed to add callsite to ELF userspace probe."); @@ -473,7 +497,7 @@ int userspace_probe_add_callsite( 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("Failed to add callsite to SDT userspace probe"); -- 2.34.1