Rough solution for Tasks 1, 2, 3
main.go: - reading /proc - iteration over entries in NNN/maps - filter glob-search for "*python3*" in pathname - find symbol and its offset in pathnanme - calculate offset in memory - add pid and offset to map TODO: encapsulating this into a module ebpf.go: - added type MapFD int, changing all function on a FD to methods This allows us to enrich the data type going forward - added bpf_update_elem() from the manpage ebpf2. .updateElement() is the verbatim wrapper to it. - added .Add/.Change/.Set methods, which call .updateElement with specific flags TODO: re-implement ebpf.go with pure go, using direct syscalls.
This commit is contained in:
parent
64f54c622d
commit
a9f0f27ee2
@ -20,8 +20,8 @@ static int bpf_create_map(
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_type = map_type,
|
||||
.key_size = key_size,
|
||||
.value_size = value_size,
|
||||
.key_size = key_size,
|
||||
.value_size = value_size,
|
||||
.max_entries = max_entries};
|
||||
|
||||
return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
|
||||
@ -31,8 +31,8 @@ int bpf_get_next_key(int fd, const void *key, void *next_key)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_fd = fd,
|
||||
.key = (__u64) (unsigned long) key,
|
||||
.next_key = (__u64) (unsigned long) next_key};
|
||||
.key = (__u64) (unsigned long) key,
|
||||
.next_key = (__u64) (unsigned long) next_key};
|
||||
|
||||
return bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
|
||||
}
|
||||
@ -41,15 +41,25 @@ int bpf_get_next_key(int fd, const void *key, void *next_key)
|
||||
int bpf_lookup_elem(int fd, const void *key, void *value)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_fd = fd,
|
||||
.key = (__u64) (unsigned long) key,
|
||||
.map_fd = fd,
|
||||
.key = (__u64) (unsigned long) key,
|
||||
.value = (__u64) (unsigned long) value,
|
||||
};
|
||||
|
||||
return bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
// TODO: add insert
|
||||
int bpf_update_elem(int fd, const void *key, const void *value, uint64_t flags)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_fd = fd,
|
||||
.key = (__u64) (unsigned long) key,
|
||||
.value = (__u64) (unsigned long) value,
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
@ -59,18 +69,26 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type MapFD int
|
||||
|
||||
// CreateMap creates an eBPF map from int->uint64. The file descriptor of the
|
||||
// created map is returned.
|
||||
func CreateMap() (int, error) {
|
||||
mapFD := C.bpf_create_map(C.BPF_MAP_TYPE_HASH, 4, 8, 64)
|
||||
return int(mapFD), nil
|
||||
func CreateMap() (MapFD, error) {
|
||||
|
||||
r, errno := C.bpf_create_map(C.BPF_MAP_TYPE_HASH, 4, 8, 64)
|
||||
|
||||
if r == -1 {
|
||||
return MapFD(r), fmt.Errorf("bpf_create_map with errno %d", errno)
|
||||
}
|
||||
|
||||
return MapFD(r), nil
|
||||
}
|
||||
|
||||
// GetMap gets the key/value pairs from the specified eBPF map as a Go map
|
||||
func GetMap(mapFD int) (map[int]uint64, error) {
|
||||
func (mfd MapFD) GetMap() (map[int]uint64, error) {
|
||||
retMap := make(map[int]uint64)
|
||||
|
||||
mapFDC := C.int(mapFD)
|
||||
mapFDC := C.int(mfd)
|
||||
keyC := C.int(0)
|
||||
nextKeyC := C.int(0)
|
||||
valC := C.uint64_t(0)
|
||||
@ -94,3 +112,29 @@ func GetMap(mapFD int) (map[int]uint64, error) {
|
||||
keyC = nextKeyC
|
||||
}
|
||||
}
|
||||
|
||||
func (mfd MapFD) Add(key int, value uint64) error {
|
||||
return mfd.updateElement(key, value, C.BPF_NOEXIST)
|
||||
}
|
||||
|
||||
func (mfd MapFD) Change(key int, value uint64) error {
|
||||
return mfd.updateElement(key, value, C.BPF_EXIST)
|
||||
}
|
||||
|
||||
func (mfd MapFD) Set(key int, value uint64) error {
|
||||
return mfd.updateElement(key, value, C.BPF_ANY)
|
||||
}
|
||||
|
||||
func (mfd MapFD) updateElement(key int, value uint64, flag C.uint64_t) error {
|
||||
|
||||
r, errno := C.bpf_update_elem(C.int(mfd),
|
||||
unsafe.Pointer(&key),
|
||||
unsafe.Pointer(&value),
|
||||
flag)
|
||||
|
||||
if r == -1 {
|
||||
return fmt.Errorf("bpf_update_elem failed with errno %d", errno)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -56,11 +56,11 @@ func main() {
|
||||
} else if offset, found := searchSymbolIn(pid_s, "*python3*", "_PyRuntime"); !found {
|
||||
continue
|
||||
} else {
|
||||
fmt.Printf("going to set (%d -> 0x%x)\n\n", pid, offset)
|
||||
mapFD.Add(pid, uint64(offset))
|
||||
}
|
||||
}
|
||||
|
||||
mapContents, err := ebpf.GetMap(mapFD)
|
||||
mapContents, err := mapFD.GetMap()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to get the map contents: %s", err)
|
||||
os.Exit(1)
|
||||
@ -161,7 +161,7 @@ func searchSymbolIn(pid, glob, symbol string) (offset uint64, ok bool) {
|
||||
|
||||
memoff := sym.Value - section.Addr + alignedOffset(section)
|
||||
|
||||
fmt.Printf("pid: %s\nsym: %#v\nsection: %#v\nmemoff: 0x%x\narange: %#v\nmap-fileoffset: 0x%x\npathname: %s\n", pid, sym, section, memoff, arange, fileoffset, pathname)
|
||||
// fmt.Printf("pid: %s\nsym: %#v\nsection: %#v\nmemoff: 0x%x\narange: %#v\nmap-fileoffset: 0x%x\npathname: %s\n", pid, sym, section, memoff, arange, fileoffset, pathname)
|
||||
|
||||
// stop when only _one_ is found
|
||||
return arange.start + memoff - fileoffset, true
|
||||
|
Loading…
Reference in New Issue
Block a user