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 = {
|
union bpf_attr attr = {
|
||||||
.map_type = map_type,
|
.map_type = map_type,
|
||||||
.key_size = key_size,
|
.key_size = key_size,
|
||||||
.value_size = value_size,
|
.value_size = value_size,
|
||||||
.max_entries = max_entries};
|
.max_entries = max_entries};
|
||||||
|
|
||||||
return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
|
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 = {
|
union bpf_attr attr = {
|
||||||
.map_fd = fd,
|
.map_fd = fd,
|
||||||
.key = (__u64) (unsigned long) key,
|
.key = (__u64) (unsigned long) key,
|
||||||
.next_key = (__u64) (unsigned long) next_key};
|
.next_key = (__u64) (unsigned long) next_key};
|
||||||
|
|
||||||
return bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
|
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)
|
int bpf_lookup_elem(int fd, const void *key, void *value)
|
||||||
{
|
{
|
||||||
union bpf_attr attr = {
|
union bpf_attr attr = {
|
||||||
.map_fd = fd,
|
.map_fd = fd,
|
||||||
.key = (__u64) (unsigned long) key,
|
.key = (__u64) (unsigned long) key,
|
||||||
.value = (__u64) (unsigned long) value,
|
.value = (__u64) (unsigned long) value,
|
||||||
};
|
};
|
||||||
|
|
||||||
return bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
|
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"
|
import "C"
|
||||||
@ -59,18 +69,26 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type MapFD int
|
||||||
|
|
||||||
// CreateMap creates an eBPF map from int->uint64. The file descriptor of the
|
// CreateMap creates an eBPF map from int->uint64. The file descriptor of the
|
||||||
// created map is returned.
|
// created map is returned.
|
||||||
func CreateMap() (int, error) {
|
func CreateMap() (MapFD, error) {
|
||||||
mapFD := C.bpf_create_map(C.BPF_MAP_TYPE_HASH, 4, 8, 64)
|
|
||||||
return int(mapFD), nil
|
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
|
// 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)
|
retMap := make(map[int]uint64)
|
||||||
|
|
||||||
mapFDC := C.int(mapFD)
|
mapFDC := C.int(mfd)
|
||||||
keyC := C.int(0)
|
keyC := C.int(0)
|
||||||
nextKeyC := C.int(0)
|
nextKeyC := C.int(0)
|
||||||
valC := C.uint64_t(0)
|
valC := C.uint64_t(0)
|
||||||
@ -94,3 +112,29 @@ func GetMap(mapFD int) (map[int]uint64, error) {
|
|||||||
keyC = nextKeyC
|
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 {
|
} else if offset, found := searchSymbolIn(pid_s, "*python3*", "_PyRuntime"); !found {
|
||||||
continue
|
continue
|
||||||
} else {
|
} 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 {
|
if err != nil {
|
||||||
fmt.Printf("Failed to get the map contents: %s", err)
|
fmt.Printf("Failed to get the map contents: %s", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -161,7 +161,7 @@ func searchSymbolIn(pid, glob, symbol string) (offset uint64, ok bool) {
|
|||||||
|
|
||||||
memoff := sym.Value - section.Addr + alignedOffset(section)
|
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
|
// stop when only _one_ is found
|
||||||
return arange.start + memoff - fileoffset, true
|
return arange.start + memoff - fileoffset, true
|
||||||
|
Loading…
Reference in New Issue
Block a user