| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- package tracer
- import (
- "debug/dwarf"
- "debug/elf"
- "errors"
- "fmt"
- "github.com/cilium/ebpf"
- . "github.com/coroot/coroot-node-agent/utils/modelse"
- klog "github.com/sirupsen/logrus"
- "io"
- "net"
- "os"
- "strings"
- )
- const (
- offsetInferServerAddr = "127.0.0.1"
- offsetInferServerPort = 54583
- bufferSize = 16
- )
- type ID struct {
- // ModPath is the module path containing the struct field package.
- //
- // If set to "std", the struct field belongs to the standard Go library.
- ModPath string
- // PkgPath package import path containing the struct field.
- PkgPath string
- // Struct is the name of the struct containing the field.
- Struct string
- // Field is the field name.
- Field string
- }
- func kernelOffsetInferServer(listener net.Listener) error {
- klog.Info("[eBPF Kernel Adapt] kernel_offset_infer_server started.")
- //cpuOnlineCount := runtime.NumCPU()
- go func() {
- for {
- conn, err := listener.Accept()
- if err != nil {
- klog.Errorf("[eBPF Kernel Adapt] Fail to accept client request: %v", err)
- return
- }
- go handleConnection(conn)
- }
- }()
- return nil
- }
- func handleConnection(conn net.Conn) {
- defer conn.Close()
- buffer := make([]byte, bufferSize)
- for {
- n, err := conn.Read(buffer)
- if err != nil {
- if err == io.EOF {
- klog.Errorf("[eBPF Kernel Adapt] client connection closed: %v", err)
- return
- }
- klog.Errorf("[eBPF Kernel Adapt] Error reading from connection: %v", err)
- return
- }
- //if n == 0 {
- // *clientCount++
- // break
- //}
- request := strings.TrimSpace(string(buffer[:n]))
- fmt.Println(request)
- if request == "hello" {
- _, err := conn.Write([]byte("OK"))
- if err != nil {
- klog.Errorf("[eBPF Kernel Adapt] Error writing response: %v", err)
- break
- }
- }
- }
- }
- func kernelOffsetInferClient() error {
- conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", offsetInferServerAddr, offsetInferServerPort))
- if err != nil {
- return fmt.Errorf("failed to connect to server: %v", err)
- }
- defer conn.Close()
- klog.Infoln("[eBPF Kernel Adapt] kernel_offset_infer_client started.")
- request := "hello"
- _, err = conn.Write([]byte(request))
- if err != nil {
- return fmt.Errorf("failed to send request to server: %v", err)
- }
- buffer := make([]byte, bufferSize)
- for {
- n, err := conn.Read(buffer)
- if err != nil {
- fmt.Printf("[eBPF Kernel Adapt] Error reading response from server: %v\n", err)
- break
- }
- if n == 0 {
- break
- }
- response := strings.TrimSpace(string(buffer[:n]))
- klog.Infoln(response)
- if response == "OK" {
- break
- }
- }
- klog.Infoln("[eBPF Kernel Adapt] kernel_offset_infer_client finished.")
- return nil
- }
- func NewID(mod, pkg, strct, field string) ID {
- return ID{ModPath: mod, PkgPath: pkg, Struct: strct, Field: field}
- }
- func gotoEntry(r *dwarf.Reader, tag dwarf.Tag, name string) bool {
- _, err := findEntry(r, tag, name)
- return err == nil
- }
- // findEntry returns the DWARF entry with a tag equal to name read from r. An
- // error is returned if the entry cannot be found.
- func findEntry(r *dwarf.Reader, tag dwarf.Tag, name string) (*dwarf.Entry, error) {
- for {
- entry, err := r.Next()
- if err == io.EOF || entry == nil {
- break
- }
- if entry.Tag == tag {
- if f, ok := entryField(entry, dwarf.AttrName); ok {
- if name == f.Val.(string) {
- return entry, nil
- }
- }
- }
- }
- return nil, errors.New("not found")
- }
- // entryField returns the DWARF field from DWARF entry e that has the passed
- // DWARF attribute a.
- func entryField(e *dwarf.Entry, a dwarf.Attr) (dwarf.Field, bool) {
- for _, f := range e.Field {
- if f.Attr == a {
- return f, true
- }
- }
- return dwarf.Field{}, false
- }
- func GetOffset(id ID, path string) (uint64, bool) {
- strct := fmt.Sprintf("%s.%s", id.PkgPath, id.Struct)
- elfF, err := elf.Open(path)
- if err != nil {
- os.Exit(1)
- }
- defer elfF.Close()
- data, err := elfF.DWARF()
- fmt.Println(err)
- r := data.Reader()
- if !gotoEntry(r, dwarf.TagStructType, strct) {
- return 0, false
- }
- e, err := findEntry(r, dwarf.TagMember, id.Field)
- if err != nil {
- return 0, false
- }
- f, ok := entryField(e, dwarf.AttrDataMemberLoc)
- if !ok {
- return 0, false
- }
- return uint64(f.Val.(int64)), true
- }
- func UpdateProcInfoToMap(collection *ebpf.Collection, pid uint32, proc any) (int, error) {
- return bpf_table_set_value(collection, MAP_PROC_INFO_MAP_NAME, pid, proc)
- }
|