-
Notifications
You must be signed in to change notification settings - Fork 228
/
types.go
155 lines (134 loc) · 7.54 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Apache License 2.0.
* See the file "LICENSE" for details.
*/
package interpreter
import (
"errors"
"unsafe"
"github.com/elastic/otel-profiling-agent/host"
"github.com/elastic/otel-profiling-agent/libpf"
"github.com/elastic/otel-profiling-agent/libpf/process"
"github.com/elastic/otel-profiling-agent/libpf/remotememory"
"github.com/elastic/otel-profiling-agent/lpm"
"github.com/elastic/otel-profiling-agent/metrics"
"github.com/elastic/otel-profiling-agent/reporter"
"github.com/elastic/otel-profiling-agent/tpbase"
)
const (
// LruFunctionCacheSize is the LRU size for caching functions for an interpreter.
// This should reflect the number of hot functions that are seen often in a trace.
LruFunctionCacheSize = 1024
// UnknownSourceFile is the source file name to use when the real one is not available
UnknownSourceFile = "<unknown>"
// TopLevelFunctionName is the name to be used when a function does not have a name,
// but we can deduce that it is at the highest possible scope (e.g for top-level PHP code)
TopLevelFunctionName = "<top-level>"
)
var (
ErrMismatchInterpreterType = errors.New("mismatched interpreter type")
)
// The following function Loader and interfaces Data and Instance work together
// as an abstraction to support language specific eBPF unwinding and host agent side symbolization
// of frames.
//
// Functionality for these interfaces is divided as follows:
//
// 1. Loader is responsible for recognizing if the given mapping/ELF DSO matches by name,
// and later by content, to an interpreter supported by the specific implementation.
// If yes, it returns Data for this specific DSO. The Loader loads and checks data
// from given ELF DSO. The intent is to load needed symbols and keep their addresses
// relative to the file virtual address space. It can also load static data from the
// DSO, such as the exact interpreter version string or number. All this is returned
// in a data structure that implements Data interface.
//
// 2. Data is the interface to operate on per-ELF DSO data. ProcessManager receives this
// interface from the Loader, and stores it in a map to cache them by FileID. That is,
// each ELF DSO is probed by the Loaders only the first time it is seen. The returned
// Data is then reused for all other processes using the same ELF DSO without need to
// extract information from it by the loader.
//
// The Attach method will populate the needed eBPF maps with the pre-parsed data from
// the Data and PID specific AttachData. E.g. it can calculate the target memory addresses
// by adding the file virtual address from cached Data and the process AttachData mapping
// "bias". If additional per-PID structures need to be maintained it can instantiate new
// Instance structures for those. Finally an Instance interface is returned: either to
// the per-PID Instance structure, or if no per-PID data is kept, the main Data structure
// can also implement this interface.
//
// 3. Instance is the interface to operate on per-PID data. This interface
// is tracked by the ProcessManager by PID and the mapped-at-address.
//
// The ProcessManager will delegate frame symbolization to this interface,
// and it will also call this interface's Detach to clean up eBPF maps release any
// per-PID resource held.
//
// The split of Data and Instance and the way the methods signatures are designed (passing ebpfMaps
// and pid) allows an interpreter implementation to keep just per-ELF information (when the xxxData
// implements both interfaces) or additionally track per-PID information (separate data types for
// the Data and Instance).
//
// Data (and Instance) should generally match one eBPF tracer implementation. However, it is
// possible to have several Loaders that would return same type of Data. For example,
// xxInterpreter 2 and xxInterpreter 3 can likely be unwound by the same unwinding strategy but
// perhaps the symbol names or the way to extract introspection data is different. Or perhaps we
// need to hard code different well known offsets in the xxData. It allows then to still
// share the Data and Instance code between these versions.
// Symbolizer is the interface to call back for frame symbolization information
type Symbolizer = reporter.SymbolReporter
// EbpfHandler provides the functionality for interpreters to interact with eBPF maps.
type EbpfHandler interface {
// UpdateInterpreterOffsets adds the given offsetRanges to the eBPF map interpreter_offsets.
UpdateInterpreterOffsets(ebpfProgIndex uint16, fileID host.FileID,
offsetRanges []libpf.Range) error
// UpdateProcData adds the given interpreter data to the named eBPF map.
UpdateProcData(typ libpf.InterpType, pid libpf.PID, data unsafe.Pointer) error
// DeleteProcData removes any data from the named eBPF map.
DeleteProcData(typ libpf.InterpType, pid libpf.PID) error
// UpdatePidInterpreterMapping updates the eBPF map pid_page_to_mapping_info
// to call given interpreter unwinder.
UpdatePidInterpreterMapping(libpf.PID, lpm.Prefix, uint8, host.FileID, uint64) error
// DeletePidInterpreterMapping removes the element specified by pid, prefix
// rom the eBPF map pid_page_to_mapping_info.
DeletePidInterpreterMapping(libpf.PID, lpm.Prefix) error
}
// Loader is a function to detect and load data from given interpreter ELF file.
// ProcessManager will call each configured Loader in order to see if additional handling and data
// is needed to unwind interpreter frames.
//
// A Loader can return one of the following value combinations:
//
// - `nil, nil`, indicating that it didn't detect the interpreter to belong to it
// - `data, nil`, indicating that it wants to handle the executable
// - `nil, error`, indicating that a permanent failure occurred during interpreter detection
type Loader func(ebpf EbpfHandler, info *LoaderInfo) (Data, error)
// Data is the interface to operate on per-ELF DSO data.
type Data interface {
// Attach checks if the given dso is supported, and loads the information
// of it to the ebpf maps.
Attach(ebpf EbpfHandler, pid libpf.PID, bias libpf.Address, rm remotememory.RemoteMemory) (
Instance, error)
}
// Instance is the interface to operate on per-PID data.
type Instance interface {
// Detach removes any information from the ebpf maps. The pid is given as argument so
// simple interpreters can use the global Data also as the Instance implementation.
Detach(ebpf EbpfHandler, pid libpf.PID) error
// SynchronizeMappings is called when the processmanager has reread process memory
// mappings. Interpreters not needing to process these events can simply ignore them
// by just returning a nil.
SynchronizeMappings(ebpf EbpfHandler, symbolReporter reporter.SymbolReporter,
pr process.Process, mappings []process.Mapping) error
// UpdateTSDInfo is called when the process C-library Thread Specific Data related
// introspection data has been updated.
UpdateTSDInfo(ebpf EbpfHandler, pid libpf.PID, info tpbase.TSDInfo) error
// Symbolize requests symbolization of the given frame, and dispatches this symbolization
// to the collection agent using Symbolizer interface. The frame's contents (frame type,
// file ID and line number) are appended to trace.
Symbolize(symbolReporter reporter.SymbolReporter, frame *host.Frame,
trace *libpf.Trace) error
// GetAndResetMetrics collects the metrics from the Instance and resets
// the counters to their initial value.
GetAndResetMetrics() ([]metrics.Metric, error)
}