Skip to content

Instantly share code, notes, and snippets.

@zhuizhuhaomeng
Last active June 4, 2025 23:37
Show Gist options
  • Save zhuizhuhaomeng/9a8676bbc74b543b9e119a85a113b2f0 to your computer and use it in GitHub Desktop.
Save zhuizhuhaomeng/9a8676bbc74b543b9e119a85a113b2f0 to your computer and use it in GitHub Desktop.
uprobe.patch
commit 646676ced3ec352abcd348fd34509d470d59d5bb
Author: lijunlong <[email protected]>
Date: Thu Jun 5 07:37:00 2025 +0800
bugfix: buildid check failed because the Offset does not equal to the VirtAddr.
$readelf -l -W envoy
Elf file type is DYN (Position-Independent Executable file)
Entry point 0x192e000
There are 12 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0002a0 0x0002a0 R 0x8
INTERP 0x0002e0 0x00000000000002e0 0x00000000000002e0 0x00001c 0x00001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x192cdec 0x192cdec R 0x1000
LOAD 0x192d000 0x000000000192e000 0x000000000192e000 0x2c95710 0x2c95710 R E 0x1000
LOAD 0x45c2740 0x00000000045c4740 0x00000000045c4740 0x267830 0x2678c0 RW 0x1000
LOAD 0x4829f70 0x000000000482cf70 0x000000000482cf70 0x0b6f70 0xc332b0 RW 0x1000
TLS 0x45c2740 0x00000000045c4740 0x00000000045c4740 0x000110 0x0026e0 R 0x40
DYNAMIC 0x48226b8 0x00000000048246b8 0x00000000048246b8 0x000200 0x000200 RW 0x8
GNU_RELRO 0x45c2740 0x00000000045c4740 0x00000000045c4740 0x267830 0x2678c0 R 0x1
GNU_EH_FRAME 0x110ae58 0x000000000110ae58 0x000000000110ae58 0x15c30c 0x15c30c R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0
NOTE 0x0002fc 0x00000000000002fc 0x00000000000002fc 0x000044 0x000044 R 0x4
diff --git a/dwflpp.h b/dwflpp.h
index d90ce9436..225c0a276 100644
--- a/dwflpp.h
+++ b/dwflpp.h
@@ -124,6 +124,12 @@ typedef std::vector<func_info> func_info_map_t;
typedef std::vector<inline_instance_info> inline_instance_map_t;
+struct elf_hdr {
+ Dwarf_Addr file_offset; // file offset
+ Dwarf_Addr vaddr_start; // start of the virtual address
+ Dwarf_Addr vaddr_end; // end of the virtual address
+};
+
struct
module_info
{
@@ -139,6 +145,7 @@ module_info
std::set<interned_string> inlined_funcs;
std::set<interned_string> plt_funcs;
std::set<std::pair<std::string,std::string> > marks; /* <provider,name> */
+ std::vector<struct elf_hdr> hdrs;
void get_symtab();
void update_symtab(cu_function_cache_t *funcs);
diff --git a/runtime/linux/task_finder2.c b/runtime/linux/task_finder2.c
index 9c2f5ad88..951720d21 100644
--- a/runtime/linux/task_finder2.c
+++ b/runtime/linux/task_finder2.c
@@ -784,6 +784,22 @@ __stp_find_file_based_vma(struct mm_struct *mm, unsigned long addr)
return vma;
}
+static unsigned long
+__stp_find_elf_base_addr(struct mm_struct *mm, struct vm_area_struct *target_vma)
+{
+ unsigned long base_addr = target_vma->vm_start;
+ struct vm_area_struct *vma;
+
+ VMA_ITERATOR(vmi, mm, 0);
+ for_each_vma(vmi, vma) {
+ if (vma->vm_file == target_vma->vm_file || vma == target_vma) {
+ base_addr = vma->vm_start;
+ break;
+ }
+ }
+
+ return base_addr;
+}
static void
__stp_call_mmap_callbacks_with_addr(struct stap_task_finder_target *tgt,
@@ -798,6 +814,7 @@ __stp_call_mmap_callbacks_with_addr(struct stap_task_finder_target *tgt,
unsigned long length = 0;
unsigned long offset = 0;
unsigned long vm_flags = 0;
+ unsigned long base_addr = 0;
// __stp_call_mmap_callbacks_with_addr() is only called when
// tsk is current, so there isn't any danger of mm going
@@ -816,7 +833,9 @@ __stp_call_mmap_callbacks_with_addr(struct stap_task_finder_target *tgt,
// Cache information we need from the vma
addr = vma->vm_start;
length = vma->vm_end - vma->vm_start;
- offset = (vma->vm_pgoff << PAGE_SHIFT);
+ base_addr = __stp_find_elf_base_addr(mm, vma);
+ //offset = (vma->vm_pgoff << PAGE_SHIFT);
+ offset = addr - base_addr;
vm_flags = vma->vm_flags;
#ifdef STAPCONF_DPATH_PATH
dentry = vma->vm_file->f_path.dentry;
@@ -1268,6 +1287,8 @@ __stp_call_mmap_callbacks_for_task(struct stap_task_finder_target *tgt,
};
struct vma_cache_t *vma_cache = NULL;
struct vma_cache_t *vma_cache_p;
+ struct file *mm_file = NULL;
+ unsigned long base_addr = 0;
// Call the mmap_callback for every vma associated with
// a file.
@@ -1331,9 +1352,15 @@ __stp_call_mmap_callbacks_for_task(struct stap_task_finder_target *tgt,
mntget(vma_cache_p->f_vfsmnt);
vma_cache_p->dentry = vma->vm_file->f_dentry;
#endif
+ if (mm_file == NULL || mm_file != vma->vm_file) {
+ mm_file = vma->vm_file;
+ base_addr = vma->vm_start;
+ }
+
vma_cache_p->addr = vma->vm_start;
vma_cache_p->length = vma->vm_end - vma->vm_start;
- vma_cache_p->offset = (vma->vm_pgoff << PAGE_SHIFT);
+ //vma_cache_p->offset = (vma->vm_pgoff << PAGE_SHIFT);
+ vma_cache_p->offset = vma->vm_start - base_addr;
vma_cache_p->vm_flags = vma->vm_flags;
vma_cache_p++;
}
diff --git a/tapsets.cxx b/tapsets.cxx
index 01fec29e3..5cd893b7c 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -2664,6 +2664,30 @@ query_module (Dwfl_Module *mod,
{
mi->dwarf_status = info_absent;
}
+
+ {
+ Dwarf_Addr load_addr;
+ Elf* elf = dwfl_module_getelf (mod, &load_addr);
+
+ // Get the load address, readelf -l -W elf | grep LOAD
+ for (int i = 0; ; i++)
+ {
+ GElf_Phdr mem;
+ GElf_Phdr *phdr;
+ phdr = gelf_getphdr (elf, i, &mem);
+ if (phdr == NULL)
+ break;
+
+ if (phdr->p_type == PT_LOAD)
+ {
+ struct elf_hdr hdr;
+ hdr.file_offset = phdr->p_offset;
+ hdr.vaddr_start = phdr->p_vaddr;
+ hdr.vaddr_end = phdr->p_vaddr + phdr->p_memsz;
+ mi->hdrs.push_back(hdr);
+ }
+ }
+ }
}
// OK, enough of that module_info caching business.
@@ -5610,9 +5634,19 @@ dwarf_derived_probe::dwarf_derived_probe(interned_string funcname,
// inode-uprobes needs an offset rather than an absolute VM address.
// ditto for userspace runtimes (dyninst)
if ((kernel_supports_inode_uprobes(q.dw.sess) || q.dw.sess.runtime_usermode_p()) &&
- section == ".absolute" && addr == dwfl_addr &&
- addr >= q.dw.module_start && addr < q.dw.module_end)
- this->addr = addr - q.dw.module_start;
+ section == ".absolute" && addr == dwfl_addr)
+ {
+ // An ELF file maybe loaded into multiple non-contiguous memory addresses,
+ for (auto it = q.dw.mod_info->hdrs.begin();
+ it != q.dw.mod_info->hdrs.end(); ++it)
+ {
+ if (it->vaddr_start <= addr && addr < it->vaddr_end)
+ {
+ this->addr = addr - it->vaddr_start + it->file_offset;
+ break;
+ }
+ }
+ }
}
else
{
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment