You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: processor.go
    path of file: ./repos/tracee/pkg/ebpf
    
    the code of the file until where you have to start completion: package ebpf

import (
	"fmt"
	"sync"

	"github.com/aquasecurity/libbpfgo/helpers"

	"github.com/aquasecurity/tracee/pkg/events"
	"github.com/aquasecurity/tracee/pkg/logger"
	"github.com/aquasecurity/tracee/pkg/proctree"
	"github.com/aquasecurity/tracee/types/trace"
)

var (
	kernelReadFileTypes map[int32]trace.KernelReadType
	onceHashCapsAdd     sync.Once // capabilities for exec hash enabled only once
)

func init() {
	initKernelReadFileTypes() // init kernelRead
    
func (t *Tracee) registerEventProcessors() {
	//
	// Process Tree Processors
	//

	// Processors registered when proctree source "events" is enabled.
	switch t.config.ProcTree.Source {
	case proctree.SourceEvents, proctree.SourceBoth:
		t.RegisterEventProcessor(events.SchedProcessFork, t.procTreeForkProcessor)
		t.RegisterEventProcessor(events.SchedProcessExec, t.procTreeExecProcessor)
		t.RegisterEventProcessor(events.SchedProcessExit, t.procTreeExitProcessor)
	}
	// Processors enriching process tree with regular pipeline events.
	if t.config.ProcTree.Source != proctree.SourceNone {
		t.RegisterEventProcessor(events.All, t.procTreeAddBinInfo)
	}
	// Processors regitered even if process tree source is disabled.
	t.RegisterEventProcessor(events.SchedProcessFork, t.procTreeForkRemoveArgs)

	//
	// DNS Cache Processors
	//

	if t.config.DNSCacheConfig.Enable {
		// TODO(nadav): Migrate to control plane signals?
		t.RegisterEventProcessor(events.NetPacketDNS, t.populateDnsCache)
	}

	//
	// Regular Pipeline Processors
	//

	t.RegisterEventProcessor(events.VfsWrite, t.processWriteEvent)
	t.RegisterEventProcessor(events.VfsWritev, t.processWriteEvent)
	t.RegisterEventProcessor(events.KernelWrite, t.processWriteEvent)
	t.RegisterEventProcessor(events.SecurityKernelReadFile, processKernelReadFile)
	t.RegisterEventProcessor(events.SecurityPostReadFile, processKernelReadFile)
	t.RegisterEventProcessor(events.SchedProcessExec, t.processSchedProcessExec)
	t.RegisterEventProcessor(events.DoInitModule, t.processDoInitModule)
	t.RegisterEventProcessor(events.HookedProcFops, t.processHookedProcFops)
	t.RegisterEventProcessor(events.PrintNetSeqOps, t.processTriggeredEvent)
	t.RegisterEventProcessor(events.PrintMemDump, t.processTriggeredEvent)
	t.RegisterEventProcessor(events.PrintMemDump, t.processPrintMemDump)
	t.RegisterEventProcessor(events.SharedObjectLoaded, t.processSharedObjectLoaded)

	//
	// Event Timestamps Normalization Processors
	//

	// Convert all time relate args to nanoseconds since epoch.
	// NOTE: Make sure to convert time related args (of your event) in here.
	t.RegisterEventProcessor(events.SchedProcessFork, t.processSchedProcessFork)
	t.RegisterEventProcessor(events.All, t.normalizeEventCtxTimes)
}