@@ -5,125 +5,71 @@ package rtld // import "go.opentelemetry.io/ebpf-profiler/interpreter/rtld"
55
66import (
77 "fmt"
8- "path"
9- "regexp"
108
119 log "github.com/sirupsen/logrus"
1210 "go.opentelemetry.io/ebpf-profiler/interpreter"
1311 "go.opentelemetry.io/ebpf-profiler/libpf"
14- "go.opentelemetry.io/ebpf-profiler/libpf/pfelf"
1512 "go.opentelemetry.io/ebpf-profiler/remotememory"
1613)
1714
18- // LdsoRegexp matches ld.so filenames across different distributions
19- var LdsoRegexp = regexp .MustCompile (
20- `^ld(?:-linux)?(?:-x86-64|-aarch64)?\.so\.\d+$|` +
21- `^ld\.so\.\d+$|` +
22- `^ld-\d+\.\d+\.so$|` +
23- `^ld-musl-[^/]+\.so\.\d+$` )
24-
2515// data holds the Uprobe link to keep it in memory
2616type data struct {
27- path string
28- usePoller bool
29- probe pfelf.USDTProbe
30- lc interpreter.LinkCloser
17+ path string
18+ address uint64
19+ lc interpreter.LinkCloser
3120}
3221
33- // instance represents a per-PID instance of the rtld interpreter
22+ // instance represents a per-PID instance of the dlopen interpreter
3423type instance struct {
3524 interpreter.InstanceStubs
36- usePoller bool
37- lc interpreter.LinkCloser
25+ lc interpreter.LinkCloser
3826}
3927
40- // Loader detects if the ELF file contains the rtld:map_complete USDT probe
28+ // Loader detects if the ELF file contains the dlopen symbol in its dynamic symbol table
4129func Loader (ebpf interpreter.EbpfHandler , info * interpreter.LoaderInfo ) (interpreter.Data , error ) {
42- // Check if this is ld.so by examining just the basename
4330 fileName := info .FileName ()
44- baseName := path .Base (fileName )
45- if ! LdsoRegexp .MatchString (baseName ) {
46- return nil , nil
47- }
4831
4932 ef , err := info .GetELF ()
5033 if err != nil {
5134 return nil , err
5235 }
5336
54- // Look for .note.stapsdt section which contains USDT probes
55- sec := ef .Section (".note.stapsdt" )
56- if sec == nil {
57- log .Debugf ("No .note.stapsdt section found in %s, will use poller fallback" , fileName )
58- return & data {
59- path : fileName ,
60- usePoller : true ,
61- }, nil
37+ // Look for the dlopen symbol in the dynamic symbol table
38+ sym , err := ef .LookupSymbol ("dlopen" )
39+ if err != nil || sym == nil {
40+ // No dlopen symbol found, this library doesn't support dynamic loading
41+ return nil , nil
6242 }
6343
64- // Parse USDT probes from the section
65- probes , err := pfelf .ParseUSDTProbes (sec )
66- if err != nil {
67- return nil , fmt .Errorf ("failed to parse USDT probes: %w" , err )
68- }
69- // Look for rtld:map_complete probe
70- for _ , probe := range probes {
71- if probe .Provider != "rtld" || probe .Name != "map_complete" {
72- continue
73- }
74- log .Debugf ("Found rtld:map_complete USDT probe in %s at 0x%x" ,
75- fileName , probe .Location )
44+ log .Debugf ("Found dlopen symbol in %s at 0x%x" , fileName , sym .Address )
7645
77- return & data {
78- probe : probe ,
79- path : fileName ,
80- }, nil
81- }
82-
83- // No rtld:map_complete probe found, use poller fallback
84- log .Debugf ("No rtld:map_complete probe found in %s, will use poller fallback" , fileName )
8546 return & data {
86- path : fileName ,
87- usePoller : true ,
47+ path : fileName ,
48+ address : uint64 ( sym . Address ) ,
8849 }, nil
8950}
9051
91- // Attach attaches the uprobe to the rtld:map_complete USDT probe or registers with poller
92- func (d * data ) Attach (ebpf interpreter.EbpfHandler , pid libpf.PID , _ libpf.Address ,
52+ // Attach attaches the uprobe to the dlopen function
53+ func (d * data ) Attach (ebpf interpreter.EbpfHandler , pid libpf.PID , bias libpf.Address ,
9354 _ remotememory.RemoteMemory ) (interpreter.Instance , error ) {
94- if d .usePoller {
95- // Register this PID with the global poller
96- // Create a trigger function that calls TriggerProcessSync on the ebpf handler
97- triggerFunc := func (triggerPID libpf.PID ) {
98- if err := ebpf .TriggerProcessSync (triggerPID ); err != nil {
99- log .Debugf ("[rtld] TriggerProcessSync failed for PID %d: %v" , triggerPID , err )
100- }
101- }
102- getPoller (triggerFunc ).registerPID (pid )
103- log .Debugf ("[rtld] Registered PID %d with poller for %s" , pid , d .path )
104-
105- return & instance {usePoller : true }, nil
106- } else {
107- prog := "usdt_rtld_map_complete"
108- lc , err := ebpf .AttachUSDTProbes (
109- pid , d .path , prog , []pfelf.USDTProbe {d .probe }, nil , nil , false )
110- if err != nil {
111- return nil , fmt .Errorf ("failed to attach uprobe to rtld:map_complete usdt: %w" , err )
112- }
113- log .Debugf ("[rtld] Using USDT probe for PID %d on %s" , pid , d .path )
114- d .lc = lc
115- return & instance {lc : lc }, nil
55+ // Attach uprobe to dlopen using the address stored during Loader
56+ lc , err := ebpf .AttachUprobe (pid , d .path , d .address , "uprobe_dlopen" )
57+ if err != nil {
58+ return nil , fmt .Errorf ("failed to attach uprobe to dlopen: %w" , err )
11659 }
60+
61+ log .Debugf ("[dlopen] Attached uprobe to dlopen for PID %d on %s at 0x%x" ,
62+ pid , d .path , d .address )
63+
64+ d .lc = lc
65+ return & instance {lc : lc }, nil
11766}
11867
119- // Detach removes the uprobe or deregisters from poller
68+ // Detach removes the uprobe
12069func (i * instance ) Detach (_ interpreter.EbpfHandler , pid libpf.PID ) error {
121- log .Debugf ("[rtld] Detach called for PID %d" , pid )
122- if i .usePoller {
123- // Deregister this PID from the global poller
124- // Pass a nil trigger function since we're just deregistering
125- getPoller (nil ).deregisterPID (pid )
126- log .Debugf ("[rtld] Deregistered PID %d from poller" , pid )
70+ log .Debugf ("[dlopen] Detach called for PID %d" , pid )
71+ if i .lc != nil {
72+ return i .lc .Detach ()
12773 }
12874 return nil
12975}
@@ -132,9 +78,9 @@ func (i *instance) Detach(_ interpreter.EbpfHandler, pid libpf.PID) error {
13278func (d * data ) Unload (_ interpreter.EbpfHandler ) {
13379 if d .lc != nil {
13480 if err := d .lc .Unload (); err != nil {
135- log .Errorf ("[rtld ] Failed to unload uprobe link: %v" , err )
81+ log .Errorf ("[dlopen ] Failed to unload uprobe link: %v" , err )
13682 }
13783 d .lc = nil
13884 }
139- log .Debugf ("[rtld ] Unloaded uprobe for %s" , d .path )
85+ log .Debugf ("[dlopen ] Unloaded uprobe for %s" , d .path )
14086}
0 commit comments