eunomia-bpf / bpftime

Userspace eBPF runtime for fast Uprobe & Syscall hook & Extensions with LLVM JIT
https://eunomia.dev/bpftime/
MIT License
693 stars 68 forks source link

[BUG] bpftime not able to attach uprobes to go runtime functions. #221

Closed amoghumesh closed 4 months ago

amoghumesh commented 4 months ago

Bug Description I'm not able to use bpftime to load uprobes onto a go binary. Here is my go program. I'm trying to attach to the time.now function in the go runtime. main.go:


import (
    "fmt"
    "time"
)

func printCurrentTime() {
    currentTime := time.Now()
    fmt.Println("Current Time: ", currentTime)
}

func main() {
    for {
        printCurrentTime()
        time.Sleep(1 * time.Second)
    }
}

Here is my example/minimal/uprobe.bpf.c that I modified for this purpose:

#define BPF_NO_GLOBAL_DATA
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

SEC("uprobe/./main:time.now")
int do_uprobe_trace(struct pt_regs *ctx)
{
        bpf_printk("time.now called.\n");
        return 0;
}

char LICENSE[] SEC("license") = "GPL";

bptime start does not print the info logs saying Attach successfully

Expected behavior bptime start prints the info logs saying Attach successfully and time.now called is printed on each iteration in main.go

Screenshots

Using Kernel uprobes 2024-02-21_11-45 2024-02-21_11-45_1

Using bpftime 2024-02-21_11-44 2024-02-21_11-44_1

OS information

Zheaoli commented 4 months ago

The root cause here is the Go special ELF runtime

For example, the following code

package main

import (
    "fmt"
    "time"
)

func printCurrentTime() {
    currentTime := time.Now()
    fmt.Println("Current Time: ", currentTime)
}

func main() {
    for {
        printCurrentTime()
        time.Sleep(1 * time.Second)
    }
}

Compile it and we can use the readelf to get the entrypoint

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4644c0

And we can the code on 0x4644c0

00000000004644c0 <_rt0_amd64_linux>:
  4644c0:   e9 fb c8 ff ff          jmp    460dc0 <_rt0_amd64>

The bootup chain is _rt0_amd64_linux->_rt0_amd64->runtime.rt0_go.abi0->runtime.mstart.abi0->main.main.

In the agent, the __libc_start_main method we hooked has not existed. So the probe is not working here https://github.com/eunomia-bpf/bpftime/blob/master/runtime/agent/agent.cpp#L61

Officeyutong commented 4 months ago

We only support dynamically linked go programs, please use cgo. We don't support statically linked go programs