|
|
@@ -1,16 +1,21 @@
|
|
|
package ebpftracer
|
|
|
|
|
|
import (
|
|
|
+ "errors"
|
|
|
+
|
|
|
+
|
|
|
"fmt"
|
|
|
+ "debug/elf"
|
|
|
|
|
|
"github.com/coroot/coroot-node-agent/utils"
|
|
|
|
|
|
"github.com/cilium/ebpf/link"
|
|
|
+ "golang.org/x/arch/x86/x86asm"
|
|
|
)
|
|
|
|
|
|
const (
|
|
|
// goServeHTTP = "net/http.serverHandler.ServeHTTP"
|
|
|
- binPath = "/home/cloudwise/rock/code/jdk8u/build/linux-x86_64-normal-server-slowdebug/jdk/lib/amd64/libnio.so"
|
|
|
+ binPath = "/root/code/jdk8u/build/linux-x86_64-normal-server-release/jdk/lib/amd64/libnio.so"
|
|
|
symbolsocketRead0 = "Java_sun_nio_ch_FileDispatcherImpl_read0"
|
|
|
)
|
|
|
|
|
|
@@ -23,14 +28,82 @@ func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, insID utils.ID) []link.Lin
|
|
|
if err != nil {
|
|
|
return nil
|
|
|
}
|
|
|
- opt := link.UprobeOptions{
|
|
|
- Offset: 103,
|
|
|
+
|
|
|
+ ef, err := elf.Open(binPath)
|
|
|
+ if err != nil {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ defer ef.Close()
|
|
|
+
|
|
|
+ symbols, err := ef.Symbols()
|
|
|
+ if err != nil {
|
|
|
+ if errors.Is(err, elf.ErrNoSymbols) {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ textSection := ef.Section(".text")
|
|
|
+ if textSection == nil {
|
|
|
+ return nil
|
|
|
}
|
|
|
- upread02, err := ex.Uprobe(symbolsocketRead0, t.uprobes["uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0"], &opt)
|
|
|
+ textSectionData, err := textSection.Data()
|
|
|
if err != nil {
|
|
|
return nil
|
|
|
}
|
|
|
- links = append(links, upread02)
|
|
|
+ textSectionLen := uint64(len(textSectionData) - 1)
|
|
|
+
|
|
|
+ // opt := link.UprobeOptions{
|
|
|
+ // Offset: 61,
|
|
|
+ // }
|
|
|
+ // upread02, err := ex.Uprobe(symbolsocketRead0, t.uprobes["uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0"], &opt)
|
|
|
+ // if err != nil {
|
|
|
+ // return nil
|
|
|
+ // }
|
|
|
+ // links = append(links, upread01)
|
|
|
+ for _, s := range symbols {
|
|
|
+ if elf.ST_TYPE(s.Info) != elf.STT_FUNC || s.Size == 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ switch s.Name {
|
|
|
+ case symbolsocketRead0:
|
|
|
+ default:
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ address := s.Value
|
|
|
+ for _, p := range ef.Progs {
|
|
|
+ if p.Type != elf.PT_LOAD || (p.Flags&elf.PF_X) == 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if p.Vaddr <= s.Value && s.Value < (p.Vaddr+p.Memsz) {
|
|
|
+ address = s.Value - p.Vaddr + p.Off
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fmt.Println("s.Name-----:", s.Name)
|
|
|
+ switch s.Name {
|
|
|
+ case symbolsocketRead0:
|
|
|
+ sStart := s.Value - textSection.Addr
|
|
|
+ sEnd := sStart + s.Size
|
|
|
+ if sEnd > textSectionLen {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ sBytes := textSectionData[sStart:sEnd]
|
|
|
+ returnOffsets := getCallNextMoveOffsets(ef.Machine, sBytes)
|
|
|
+ if len(returnOffsets) == 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ for _, offset := range returnOffsets {
|
|
|
+ l, err := ex.Uprobe(s.Name, t.uprobes["uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0"], &link.UprobeOptions{Address: address, Offset: uint64(offset)})
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("failed to attach uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0 uprobe")
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ links = append(links, l)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
if len(links) == 0 {
|
|
|
return nil
|
|
|
@@ -38,3 +111,25 @@ func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, insID utils.ID) []link.Lin
|
|
|
fmt.Println("jvm uprobes attached")
|
|
|
return links
|
|
|
}
|
|
|
+
|
|
|
+func getCallNextMoveOffsets(machine elf.Machine, instructions []byte) []int {
|
|
|
+ var res []int
|
|
|
+ firstCall := 0
|
|
|
+ switch machine {
|
|
|
+ case elf.EM_X86_64:
|
|
|
+ for i := 0; i < len(instructions); {
|
|
|
+ ins, err := x86asm.Decode(instructions[i:], 64)
|
|
|
+ if err == nil && ins.Op == x86asm.CALL {
|
|
|
+ if firstCall == 0{
|
|
|
+ firstCall = 1
|
|
|
+ }else{
|
|
|
+ i += ins.Len
|
|
|
+ res = append(res, i)
|
|
|
+ return res
|
|
|
+ }
|
|
|
+ }
|
|
|
+ i += ins.Len
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return res
|
|
|
+}
|