public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] libbpf: Fix uprobe offset calculation
@ 2025-03-07 14:01 Hengqi Chen
  2025-03-08  6:48 ` Yonghong Song
  0 siblings, 1 reply; 7+ messages in thread
From: Hengqi Chen @ 2025-03-07 14:01 UTC (permalink / raw)
  To: bpf, andrii, eddyz87, deso; +Cc: hengqi.chen

As reported on libbpf-rs issue([0]), the current implementation
may resolve symbol to a wrong offset and thus missing uprobe
event. Calculate the symbol offset from program header instead.
See the BCC implementation (which in turn used by bpftrace) and
the spec ([1]) for references.

  [0]: https://github.com/libbpf/libbpf-rs/issues/1110
  [1]: https://refspecs.linuxfoundation.org/elf/

Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
---
 tools/lib/bpf/elf.c | 32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/tools/lib/bpf/elf.c b/tools/lib/bpf/elf.c
index 823f83ad819c..9b561c8d1eec 100644
--- a/tools/lib/bpf/elf.c
+++ b/tools/lib/bpf/elf.c
@@ -260,13 +260,29 @@ static bool symbol_match(struct elf_sym_iter *iter, int sh_type, struct elf_sym
  * for shared libs) into file offset, which is what kernel is expecting
  * for uprobe/uretprobe attachment.
  * See Documentation/trace/uprobetracer.rst for more details. This is done
- * by looking up symbol's containing section's header and using iter's virtual
- * address (sh_addr) and corresponding file offset (sh_offset) to transform
+ * by looking up symbol's containing program header and using its virtual
+ * address (p_vaddr) and corresponding file offset (p_offset) to transform
  * sym.st_value (virtual address) into desired final file offset.
  */
-static unsigned long elf_sym_offset(struct elf_sym *sym)
+static unsigned long elf_sym_offset(Elf *elf, struct elf_sym *sym)
 {
-	return sym->sym.st_value - sym->sh.sh_addr + sym->sh.sh_offset;
+	size_t nhdrs, i;
+	GElf_Phdr phdr;
+
+	if (elf_getphdrnum(elf, &nhdrs))
+		return -1;
+
+	for (i = 0; i < nhdrs; i++) {
+		if (!gelf_getphdr(elf, (int)i, &phdr))
+			continue;
+		if (phdr.p_type != PT_LOAD || !(phdr.p_flags & PF_X))
+			continue;
+		if (sym->sym.st_value >= phdr.p_vaddr &&
+		    sym->sym.st_value < (phdr.p_vaddr + phdr.p_memsz))
+			return sym->sym.st_value - phdr.p_vaddr + phdr.p_offset;
+	}
+
+	return -1;
 }
 
 /* Find offset of function name in the provided ELF object. "binary_path" is
@@ -329,7 +345,7 @@ long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name)
 
 			if (ret > 0) {
 				/* handle multiple matches */
-				if (elf_sym_offset(sym) == ret) {
+				if (elf_sym_offset(elf, sym) == ret) {
 					/* same offset, no problem */
 					continue;
 				} else if (last_bind != STB_WEAK && cur_bind != STB_WEAK) {
@@ -346,7 +362,7 @@ long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name)
 				}
 			}
 
-			ret = elf_sym_offset(sym);
+			ret = elf_sym_offset(elf, sym);
 			last_bind = cur_bind;
 		}
 		if (ret > 0)
@@ -445,7 +461,7 @@ int elf_resolve_syms_offsets(const char *binary_path, int cnt,
 			goto out;
 
 		while ((sym = elf_sym_iter_next(&iter))) {
-			unsigned long sym_offset = elf_sym_offset(sym);
+			unsigned long sym_offset = elf_sym_offset(elf_fd.elf, sym);
 			int bind = GELF_ST_BIND(sym->sym.st_info);
 			struct symbol *found, tmp = {
 				.name = sym->name,
@@ -534,7 +550,7 @@ int elf_resolve_pattern_offsets(const char *binary_path, const char *pattern,
 			if (err)
 				goto out;
 
-			offsets[cnt++] = elf_sym_offset(sym);
+			offsets[cnt++] = elf_sym_offset(elf_fd.elf, sym);
 		}
 
 		/* If we found anything in the first symbol section,
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-03-13 21:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-07 14:01 [PATCH] libbpf: Fix uprobe offset calculation Hengqi Chen
2025-03-08  6:48 ` Yonghong Song
2025-03-11  5:16   ` Hengqi Chen
2025-03-12 18:47     ` Andrii Nakryiko
2025-03-13  4:23       ` Hengqi Chen
2025-03-13 14:30         ` Jiri Olsa
2025-03-13 21:11           ` Andrii Nakryiko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox