|
|
@@ -2,6 +2,7 @@ package ebpftracer
|
|
|
|
|
|
import (
|
|
|
"context"
|
|
|
+ "debug/dwarf"
|
|
|
"debug/elf"
|
|
|
debugelf "debug/elf"
|
|
|
"fmt"
|
|
|
@@ -19,44 +20,209 @@ import (
|
|
|
"golang.org/x/sync/semaphore"
|
|
|
)
|
|
|
|
|
|
+type uprobesDef struct {
|
|
|
+ Name string
|
|
|
+ Offset uint64
|
|
|
+ EntAddress uint64
|
|
|
+ RetAddress uint64
|
|
|
+}
|
|
|
+
|
|
|
func (t *Tracer) stack() error {
|
|
|
- // uprobes := []tracer.Uprobe{}
|
|
|
if t.disableL7Tracing {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+ binType := "dotnet"
|
|
|
+ MatchString := ".*HandleFunc|.*main.*|testfun.*|.*serverHandler.*|.*ServeHTTP.*"
|
|
|
+ dbgpath := ""
|
|
|
+
|
|
|
ENV_PID := os.Getenv("FILTER_PID")
|
|
|
WHITE_LIST := os.Getenv("WHITE_LIST")
|
|
|
+ BIN_TYPE := os.Getenv("BIN_TYPE")
|
|
|
+ DBG_PATH := os.Getenv("DBG_PATH")
|
|
|
+
|
|
|
if ENV_PID == "" {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
- MatchString := ".*HandleFunc|.*main.*|testfun.*|.*serverHandler.*|.*ServeHTTP.*"
|
|
|
-
|
|
|
if WHITE_LIST != "" {
|
|
|
MatchString = WHITE_LIST
|
|
|
}
|
|
|
|
|
|
- fmt.Println("UprobesMatchString::: init", MatchString)
|
|
|
+ if DBG_PATH != "" {
|
|
|
+ dbgpath = DBG_PATH
|
|
|
+ }
|
|
|
+
|
|
|
+ if BIN_TYPE != "" {
|
|
|
+ binType = BIN_TYPE
|
|
|
+ }
|
|
|
+
|
|
|
+ fmt.Println("UprobesMatchString:::init", MatchString)
|
|
|
|
|
|
pid, _ := strconv.ParseInt(ENV_PID, 10, 32)
|
|
|
path := proc.Path(uint32(pid), "exe")
|
|
|
|
|
|
- t.Uprobes, _ = t.getUprobes(path, MatchString)
|
|
|
+ if dbgpath != "" {
|
|
|
+ t.Uprobes, _ = t.getJavaAOTUprobes(binType, path, dbgpath, MatchString)
|
|
|
+ } else {
|
|
|
+ t.Uprobes, _ = t.getUprobes(path, MatchString)
|
|
|
+ }
|
|
|
+
|
|
|
t.UprobesMap = map[string]tracer.Uprobe{}
|
|
|
- fmt.Println("UprobesMap::: init")
|
|
|
+ fmt.Println("UprobesMap:::init")
|
|
|
for _, up := range t.Uprobes {
|
|
|
fmt.Println("UprobesMap:::", up.Funcname)
|
|
|
- t.UprobesMap[fmt.Sprintf("%s", up.Funcname)] = up
|
|
|
+ t.UprobesMap[fmt.Sprintf("%s-%s", up.Funcname, up.Address)] = up
|
|
|
}
|
|
|
links := t.attachUprobes(path, t.Uprobes)
|
|
|
t.links = append(t.links, links...)
|
|
|
|
|
|
// defer t.detachUprobes(links)
|
|
|
-
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+func (t *Tracer) getJavaAOTUprobes(binType, path string, dbgpath string, MatchString string) ([]tracer.Uprobe, error) {
|
|
|
+ uprobes := []tracer.Uprobe{}
|
|
|
+
|
|
|
+ elfFile, err := elf.Open(path)
|
|
|
+
|
|
|
+ funSection := ".text"
|
|
|
+
|
|
|
+ if binType == "dotnet" {
|
|
|
+ funSection = "__managedcode"
|
|
|
+ }
|
|
|
+
|
|
|
+ textSection := elfFile.Section(funSection)
|
|
|
+ if textSection == nil {
|
|
|
+ fmt.Println("no text section", nil)
|
|
|
+ return nil, nil
|
|
|
+ }
|
|
|
+ textSectionData, err := textSection.Data()
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("failed to read text section", err)
|
|
|
+ return nil, nil
|
|
|
+ }
|
|
|
+ textSectionLen := uint64(len(textSectionData) - 1)
|
|
|
+
|
|
|
+ dwarfFile, err := elf.Open(dbgpath)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ log.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ dwarfData, err := dwarfFile.DWARF()
|
|
|
+ if err != nil {
|
|
|
+ log.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ entryReader := dwarfData.Reader()
|
|
|
+
|
|
|
+ // var targetAddress uint64
|
|
|
+
|
|
|
+ listEntry := make(map[dwarf.Offset]uprobesDef)
|
|
|
+ SpecListEntry := []dwarf.Entry{}
|
|
|
+
|
|
|
+ for {
|
|
|
+ entry, err := entryReader.Next()
|
|
|
+ if err == io.EOF {
|
|
|
+ // We've reached the end of DWARF entries
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalf("Error reading entry: %v", err)
|
|
|
+ }
|
|
|
+ if entry == nil {
|
|
|
+ log.Println("Warning: a nil entry was returned with no error")
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if entry.Tag == dwarf.TagSubprogram {
|
|
|
+ // fmt.Printf("entry address: %x, %d\n", entry.Offset, entry.Children)
|
|
|
+ funName, _ := entry.Val(dwarf.AttrName).(string)
|
|
|
+ found, _ := regexp.MatchString(MatchString, funName)
|
|
|
+ if found {
|
|
|
+ entAddress, _ := entry.Val(dwarf.AttrLowpc).(uint64)
|
|
|
+ retAddress, _ := entry.Val(dwarf.AttrHighpc).(uint64)
|
|
|
+ // fmt.Printf("Function %s address: %x, %x\n", funName, address, entry.Offset)
|
|
|
+ uprobes := uprobesDef{}
|
|
|
+ uprobes.EntAddress = entAddress
|
|
|
+ uprobes.RetAddress = retAddress
|
|
|
+ uprobes.Offset = uint64(entry.Offset)
|
|
|
+ uprobes.Name = funName
|
|
|
+
|
|
|
+ listEntry[entry.Offset] = uprobes
|
|
|
+ }
|
|
|
+
|
|
|
+ specAddr, _ := entry.Val(dwarf.AttrSpecification).(dwarf.Offset)
|
|
|
+ lowpc := entry.Val(dwarf.AttrLowpc)
|
|
|
+ if lowpc != nil && specAddr > 0 && lowpc.(uint64) > 0 {
|
|
|
+ // fmt.Printf("AttrSpecification address: %x, %x\n", specAddr, entry.Offset)
|
|
|
+ SpecListEntry = append(SpecListEntry, *entry)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range SpecListEntry {
|
|
|
+ specAddr, _ := v.Val(dwarf.AttrSpecification).(dwarf.Offset)
|
|
|
+ // fmt.Printf("SpecListEntrySpecListEntrySpecListEntry Attach Function: %x\n", specAddr)
|
|
|
+ _, ok := listEntry[specAddr]
|
|
|
+ if ok {
|
|
|
+ vv := listEntry[specAddr]
|
|
|
+ entAddr := v.Val(dwarf.AttrLowpc)
|
|
|
+ if entAddr != nil {
|
|
|
+ vv.EntAddress = entAddr.(uint64)
|
|
|
+ }
|
|
|
+ retAddr := v.Val(dwarf.AttrHighpc)
|
|
|
+ if retAddr != nil {
|
|
|
+ switch retAddr.(type) {
|
|
|
+ case uint64:
|
|
|
+ vv.RetAddress = uint64(retAddr.(uint64))
|
|
|
+ case int64:
|
|
|
+ vv.RetAddress = uint64(retAddr.(int64))
|
|
|
+ default:
|
|
|
+ fmt.Println("Unknown type")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ listEntry[specAddr] = vv
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range listEntry {
|
|
|
+ fmt.Printf("Need Attach Function %s address: %x, %x\n", v.Name, v.EntAddress, v.RetAddress)
|
|
|
+
|
|
|
+ // 函数入口加入待 attach 列表
|
|
|
+ uprobes = append(uprobes, tracer.Uprobe{
|
|
|
+ Funcname: v.Name, // 函数名
|
|
|
+ Location: tracer.AtEntry, // 入口
|
|
|
+ Address: v.EntAddress, // 函数地址
|
|
|
+ AbsOffset: 0, // 函数相对 ELF 偏移
|
|
|
+ RelOffset: 0, // 函数真实偏移
|
|
|
+ })
|
|
|
+
|
|
|
+ sStart := v.EntAddress - textSection.Addr
|
|
|
+ sSize := v.RetAddress
|
|
|
+ if v.RetAddress > v.EntAddress {
|
|
|
+ sSize = v.RetAddress - v.EntAddress
|
|
|
+ }
|
|
|
+ sEnd := sStart + sSize
|
|
|
+ if sEnd > textSectionLen {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ sBytes := textSectionData[sStart:sEnd]
|
|
|
+ returnOffsets := getReturnOffsets(elfFile.Machine, sBytes)
|
|
|
+
|
|
|
+ for _, offset := range returnOffsets {
|
|
|
+ uprobes = append(uprobes, tracer.Uprobe{
|
|
|
+ Funcname: v.Name,
|
|
|
+ Location: tracer.AtRet,
|
|
|
+ Address: v.EntAddress,
|
|
|
+ AbsOffset: uint64(offset),
|
|
|
+ RelOffset: 0,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return uprobes, nil
|
|
|
+}
|
|
|
+
|
|
|
func (t *Tracer) getUprobes(path string, MatchString string) ([]tracer.Uprobe, error) {
|
|
|
uprobes := []tracer.Uprobe{}
|
|
|
|
|
|
@@ -109,7 +275,7 @@ func (t *Tracer) getUprobes(path string, MatchString string) ([]tracer.Uprobe, e
|
|
|
|
|
|
if found {
|
|
|
// 匹配到了加入 attachFuncs 列表
|
|
|
- fmt.Println("Fuck This: ", symbol.Name)
|
|
|
+ fmt.Printf("Fuck This: %s, %x\n", symbol.Name, symbol.Value)
|
|
|
// attachFuncs = append(attachFuncs, symbol.Name)
|
|
|
// 根据函数名拿到当前函数的符号结构体
|
|
|
sym := symnames[symbol.Name]
|
|
|
@@ -169,14 +335,10 @@ func (t *Tracer) attachUprobes(path string, uprobes []tracer.Uprobe) []link.Link
|
|
|
if err != nil {
|
|
|
return nil
|
|
|
}
|
|
|
- fmt.Println("AttachAttachAttach", path)
|
|
|
-
|
|
|
- for i, up := range t.uprobes {
|
|
|
- fmt.Println("attachingERROR---", i, up)
|
|
|
- }
|
|
|
+ fmt.Println("Attach Start", path)
|
|
|
|
|
|
for i, up := range uprobes {
|
|
|
- fmt.Printf("attaching %d -> %d -> %s -> 0x%x -> 0x%x\n", i, len(uprobes), up.Funcname, up.AbsOffset, up.Address)
|
|
|
+ fmt.Printf("attaching %d -> %d -> %s -> 0x%x -> 0x%x -> 0x%x\n", i, len(uprobes), up.Funcname, up.AbsOffset, up.Address, up.AbsOffset+up.Address)
|
|
|
var prog *ebpf.Program
|
|
|
switch up.Location {
|
|
|
case tracer.AtEntry:
|
|
|
@@ -184,13 +346,12 @@ func (t *Tracer) attachUprobes(path string, uprobes []tracer.Uprobe) []link.Link
|
|
|
case tracer.AtRet:
|
|
|
prog = t.uprobes["ret"]
|
|
|
}
|
|
|
- fmt.Println("progprogprogprogprogprog---", prog)
|
|
|
- up, err := ex.Uprobe(up.Funcname, prog, &link.UprobeOptions{Address: up.Address, Offset: up.AbsOffset})
|
|
|
+ uplink, err := ex.Uprobe(up.Funcname, prog, &link.UprobeOptions{Address: up.Address, Offset: up.AbsOffset})
|
|
|
if err != nil {
|
|
|
- fmt.Println("attachingERROR", err)
|
|
|
+ fmt.Printf("attachingERROR:%v, %v, %v\n", err, up, uplink)
|
|
|
// return nil
|
|
|
} else {
|
|
|
- links = append(links, up)
|
|
|
+ links = append(links, uplink)
|
|
|
}
|
|
|
}
|
|
|
return links
|