diff --git a/interpreter/apmint/apmint.go b/interpreter/apmint/apmint.go index 5ac60895a..bb4eee195 100644 --- a/interpreter/apmint/apmint.go +++ b/interpreter/apmint/apmint.go @@ -133,6 +133,9 @@ func (d data) Attach(ebpf interpreter.EbpfHandler, pid libpf.PID, }, nil } +func (d data) Unload(_ interpreter.EbpfHandler) { +} + type Instance struct { serviceName string socket *apmAgentSocket diff --git a/interpreter/dotnet/data.go b/interpreter/dotnet/data.go index 0abb4b509..407a210c0 100644 --- a/interpreter/dotnet/data.go +++ b/interpreter/dotnet/data.go @@ -159,6 +159,9 @@ func (d *dotnetData) Attach(ebpf interpreter.EbpfHandler, pid libpf.PID, bias li }, nil } +func (d *dotnetData) Unload(_ interpreter.EbpfHandler) { +} + func (d *dotnetData) loadIntrospectionData() { vms := &d.vmStructs diff --git a/interpreter/hotspot/data.go b/interpreter/hotspot/data.go index 0084a89cc..c49bcb06c 100644 --- a/interpreter/hotspot/data.go +++ b/interpreter/hotspot/data.go @@ -381,6 +381,9 @@ func (d *hotspotData) Attach(_ interpreter.EbpfHandler, _ libpf.PID, bias libpf. }, nil } +func (d *hotspotData) Unload(_ interpreter.EbpfHandler) { +} + // locateJvmciVMStructs attempts to heuristically locate the JVMCI VM structs by // searching for references to the string `Klass_vtable_start_offset`. In all JVM // versions >= 9.0, this corresponds to the first entry in the VM structs: diff --git a/interpreter/nodev8/v8.go b/interpreter/nodev8/v8.go index e6fed5827..89554f2c7 100644 --- a/interpreter/nodev8/v8.go +++ b/interpreter/nodev8/v8.go @@ -1877,6 +1877,9 @@ func (d *v8Data) Attach(ebpf interpreter.EbpfHandler, pid libpf.PID, _ libpf.Add }, nil } +func (d *v8Data) Unload(_ interpreter.EbpfHandler) { +} + func (d *v8Data) readIntrospectionData(ef *pfelf.File, syms libpf.SymbolFinder) error { // Read the variables from the pfelf.File so we avoid failures if the process // exists during extraction of the introspection data. diff --git a/interpreter/perl/data.go b/interpreter/perl/data.go index d2489678b..6a76081a5 100644 --- a/interpreter/perl/data.go +++ b/interpreter/perl/data.go @@ -162,6 +162,9 @@ func (d *perlData) Attach(_ interpreter.EbpfHandler, _ libpf.PID, bias libpf.Add }, nil } +func (d *perlData) Unload(_ interpreter.EbpfHandler) { +} + func newData(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo, ef *pfelf.File) (*perlData, error) { // The version is encoded in these globals since Perl 5.15.0. diff --git a/interpreter/php/opcache.go b/interpreter/php/opcache.go index 8bf435e21..5e5107643 100644 --- a/interpreter/php/opcache.go +++ b/interpreter/php/opcache.go @@ -246,6 +246,9 @@ func (d *opcacheData) Attach(_ interpreter.EbpfHandler, _ libpf.PID, bias libpf. }, nil } +func (d *opcacheData) Unload(_ interpreter.EbpfHandler) { +} + func determineOPCacheVersion(ef *pfelf.File) (uint, error) { // In contrast to interpreterphp, the opcache actually contains // a really straightforward way to recover the version. As the opcache diff --git a/interpreter/php/php.go b/interpreter/php/php.go index 95313f863..5b6206adb 100644 --- a/interpreter/php/php.go +++ b/interpreter/php/php.go @@ -146,6 +146,9 @@ func (d *phpData) Attach(ebpf interpreter.EbpfHandler, pid libpf.PID, bias libpf return instance, nil } +func (d *phpData) Unload(_ interpreter.EbpfHandler) { +} + func versionExtract(rodata string) (uint, error) { matches := versionMatch.FindStringSubmatch(rodata) if matches == nil { diff --git a/interpreter/python/python.go b/interpreter/python/python.go index c73813ead..e5db89604 100644 --- a/interpreter/python/python.go +++ b/interpreter/python/python.go @@ -148,6 +148,9 @@ func (d *pythonData) Attach(_ interpreter.EbpfHandler, _ libpf.PID, bias libpf.A return i, nil } +func (d *pythonData) Unload(_ interpreter.EbpfHandler) { +} + // pythonCodeObject contains the information we cache for a corresponding // Python interpreter's PyCodeObject structures. type pythonCodeObject struct { diff --git a/interpreter/ruby/ruby.go b/interpreter/ruby/ruby.go index 24fe7fc3e..66f04b201 100644 --- a/interpreter/ruby/ruby.go +++ b/interpreter/ruby/ruby.go @@ -232,6 +232,9 @@ func (r *rubyData) Attach(ebpf interpreter.EbpfHandler, pid libpf.PID, bias libp }, nil } +func (r *rubyData) Unload(_ interpreter.EbpfHandler) { +} + // rubyIseqBodyPC holds a reported address to a iseq_constant_body and Ruby VM program counter // combination and is used as key in the cache. type rubyIseqBodyPC struct { diff --git a/interpreter/types.go b/interpreter/types.go index 3513dfd50..591ca60c9 100644 --- a/interpreter/types.go +++ b/interpreter/types.go @@ -120,6 +120,9 @@ type Data interface { // of it to the ebpf maps. Attach(ebpf EbpfHandler, pid libpf.PID, bias libpf.Address, rm remotememory.RemoteMemory) ( Instance, error) + + // Unload can undo any allocations or eBPF entries the Loader function created + Unload(ebpf EbpfHandler) } // Instance is the interface to operate on per-PID data. diff --git a/processmanager/execinfomanager/manager.go b/processmanager/execinfomanager/manager.go index 135da84d9..e0d79148a 100644 --- a/processmanager/execinfomanager/manager.go +++ b/processmanager/execinfomanager/manager.go @@ -269,6 +269,9 @@ func (mgr *ExecutableInfoManager) RemoveOrDecRef(fileID host.FileID) error { if err := state.unloadDeltas(fileID, &info.mapRef); err != nil { return fmt.Errorf("failed remove fileID 0x%x from BPF maps: %w", fileID, err) } + if info.Data != nil { + info.Data.Unload(state.ebpf) + } delete(state.executables, fileID) case 0: // This should be unreachable.