@@ -10,7 +10,6 @@ package beam // import "go.opentelemetry.io/ebpf-profiler/interpreter/beam"
1010
1111import (
1212 "fmt"
13- "os"
1413 "regexp"
1514 "strconv"
1615 "strings"
@@ -35,10 +34,9 @@ import "C"
3534
3635var (
3736 // regex for matching the process name
38- beamRegex = regexp .MustCompile (`beam.smp` )
39- _ interpreter.Data = & beamData {}
40- _ interpreter.Instance = & beamInstance {}
41- BogusFileID = libpf .NewFileID (0xf00d , 0x1001 )
37+ beamRegex = regexp .MustCompile (`beam.smp` )
38+ _ interpreter.Data = & beamData {}
39+ _ interpreter.Instance = & beamInstance {}
4240)
4341
4442type beamData struct {
@@ -58,24 +56,6 @@ type beamInstance struct {
5856 rangesPtr libpf.Address
5957 codeIndexPtr libpf.Address
6058 atomTable libpf.Address
61- // mappings is indexed by the Mapping to its generation
62- mappings map [process.Mapping ]* uint32
63- // prefixes is indexed by the prefix added to ebpf maps (to be cleaned up) to its generation
64- prefixes map [lpm.Prefix ]* uint32
65- // mappingGeneration is the current generation (so old entries can be pruned)
66- mappingGeneration uint32
67- }
68-
69- type beamRange struct {
70- start libpf.Address
71- end libpf.Address
72- }
73-
74- type beamRanges struct {
75- modules * beamRange
76- n uint64
77- allocated uint64
78- mid libpf.Address
7959}
8060
8161func readSymbolValue (ef * pfelf.File , name libpf.SymbolName ) ([]byte , error ) {
@@ -118,7 +98,6 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr
11898 if matches == nil {
11999 return nil , nil
120100 }
121- log .Infof ("BEAM interpreter found: %v" , matches )
122101
123102 ef , err := info .GetELF ()
124103 if err != nil {
@@ -135,15 +114,6 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr
135114 return nil , err
136115 }
137116
138- interpRanges , err := info .GetSymbolAsRanges (libpf .SymbolName ("process_main" ))
139- if err != nil {
140- return nil , err
141- }
142-
143- if err = ebpf .UpdateInterpreterOffsets (support .ProgUnwindBEAM , info .FileID (), interpRanges ); err != nil {
144- return nil , err
145- }
146-
147117 // "the_active_code_index" and "r" symbols are from:
148118 // https://github.com/erlang/otp/blob/OTP-27.2.4/erts/emulator/beam/beam_ranges.c#L62
149119 the_active_code_index , err := ef .LookupSymbolAddress ("the_active_code_index" )
@@ -170,13 +140,13 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr
170140 erts_atom_table : uint64 (erts_atom_table ),
171141 }
172142
173- log .Infof ("BEAM loaded %v " , d )
143+ log .Infof ("BEAM loaded, OTP version %d " , otpVersion )
174144
175145 return d , nil
176146}
177147
178148func (d * beamData ) Attach (ebpf interpreter.EbpfHandler , pid libpf.PID , bias libpf.Address , rm remotememory.RemoteMemory ) (interpreter.Instance , error ) {
179- log .Infof ("BEAM interpreter attaching, bias: %x" , bias )
149+ log .Infof ("BEAM attaching, bias: 0x %x" , bias )
180150
181151 data := C.BEAMProcInfo {
182152 version : C .u32 (d .version ),
@@ -194,16 +164,13 @@ func (d *beamData) Attach(ebpf interpreter.EbpfHandler, pid libpf.PID, bias libp
194164 rangesPtr : bias + libpf .Address (d .r ),
195165 codeIndexPtr : bias + libpf .Address (d .the_active_code_index ),
196166 atomTable : bias + libpf .Address (d .erts_atom_table ),
197- mappings : make (map [process.Mapping ]* uint32 ),
198- prefixes : make (map [lpm.Prefix ]* uint32 ),
199167 }, nil
200168}
201169
202170func (d * beamData ) Unload (_ interpreter.EbpfHandler ) {
203171}
204172
205- func (i * beamInstance ) SynchronizeMappingsFromBEAMRanges (ebpf interpreter.EbpfHandler ,
206- _ reporter.SymbolReporter , pr process.Process , mappings []process.Mapping ) error {
173+ func (i * beamInstance ) SynchronizeMappings (ebpf interpreter.EbpfHandler , _ reporter.SymbolReporter , pr process.Process , mappings []process.Mapping ) error {
207174 pid := pr .PID ()
208175
209176 codeIndex := i .rm .Uint64 (i .codeIndexPtr )
@@ -215,6 +182,9 @@ func (i *beamInstance) SynchronizeMappingsFromBEAMRanges(ebpf interpreter.EbpfHa
215182 high := i .rm .Ptr (i .rm .Ptr (activeRanges ) + libpf .Address (16 * n ) + 8 )
216183
217184 log .Infof ("Enabling BEAM for %#x - %#x" , low , high )
185+
186+ // TODO: I think this is resulting in the following error (figure out why):
187+ // ERRO[0004] Failed to handle new anonymous mapping for PID 375011: update: key already exists
218188 prefixes , err := lpm .CalculatePrefixList (uint64 (low ), uint64 (high ))
219189 if err != nil {
220190 return fmt .Errorf ("new anonymous mapping lpm failure %#x - %#x" , low , high )
@@ -229,121 +199,6 @@ func (i *beamInstance) SynchronizeMappingsFromBEAMRanges(ebpf interpreter.EbpfHa
229199 return nil
230200}
231201
232- func (i * beamInstance ) SynchronizeMappings (ebpf interpreter.EbpfHandler ,
233- _ reporter.SymbolReporter , pr process.Process , mappings []process.Mapping ) error {
234- pid := pr .PID ()
235- i .mappingGeneration ++
236- for idx := range mappings {
237- m := & mappings [idx ]
238-
239- if ! m .IsExecutable () {
240- continue
241- }
242-
243- // log.Infof("Synchronizing executable Mapping %#x/%#x", m.Vaddr, m.Length)
244-
245- if ! m .IsAnonymous () {
246- continue
247- }
248-
249- if _ , exists := i .mappings [* m ]; exists {
250- * i .mappings [* m ] = i .mappingGeneration
251- continue
252- }
253-
254- // Generate a new uint32 pointer which is shared for mapping and the prefixes it owns
255- // so updating the mapping above will reflect to prefixes also.
256- mappingGeneration := i .mappingGeneration
257- i .mappings [* m ] = & mappingGeneration
258-
259- log .Infof ("Enabling BEAM for range %#x/%#x" , m .Vaddr , m .Length )
260-
261- prefixes , err := lpm .CalculatePrefixList (m .Vaddr , m .Vaddr + m .Length )
262- if err != nil {
263- return fmt .Errorf ("new anonymous mapping lpm failure %#x/%#x" , m .Vaddr , m .Length )
264- }
265-
266- for _ , prefix := range prefixes {
267- _ , exists := i .prefixes [prefix ]
268- if ! exists {
269- err := ebpf .UpdatePidInterpreterMapping (pid , prefix , support .ProgUnwindBEAM , 0 , 0 )
270- if err != nil {
271- return err
272- }
273- }
274- i .prefixes [prefix ] = & mappingGeneration
275- }
276- }
277-
278- // Remove prefixes not seen
279- for prefix , generationPtr := range i .prefixes {
280- if * generationPtr == i .mappingGeneration {
281- continue
282- }
283- log .Infof ("Delete prefix %#v" , prefix )
284- _ = ebpf .DeletePidInterpreterMapping (pid , prefix )
285- delete (i .prefixes , prefix )
286- }
287- for m , generationPtr := range i .mappings {
288- if * generationPtr == i .mappingGeneration {
289- continue
290- }
291- log .Infof ("Disabling mapping for %#x/%#x" , m .Vaddr , m .Length )
292- delete (i .mappings , m )
293- }
294-
295- return nil
296- }
297-
298- func (i * beamInstance ) SynchronizeMappingsFromJITDump (ebpf interpreter.EbpfHandler ,
299- _ reporter.SymbolReporter , pr process.Process , mappings []process.Mapping ) error {
300- pid := pr .PID ()
301- file , err := os .Open (fmt .Sprintf ("/tmp/jit-%d.dump" , uint32 (pid )))
302- if err != nil {
303- return err
304- }
305- defer file .Close ()
306-
307- header , err := ReadJITDumpHeader (file )
308- if err != nil {
309- return err
310- }
311- log .Infof ("Parsed header: %v" , * header )
312-
313- for recordHeader , err := ReadJITDumpRecordHeader (file ); err == nil ; recordHeader , err = ReadJITDumpRecordHeader (file ) {
314- switch recordHeader .ID {
315- case JITCodeLoad :
316- record , name , err := ReadJITDumpRecordCodeLoad (file , recordHeader )
317- if err != nil {
318- return err
319- }
320-
321- log .Infof ("JITDump Code Load %s @ 0x%x (%d bytes)" , name , record .CodeAddr , record .CodeSize )
322-
323- prefixes , err := lpm .CalculatePrefixList (record .CodeAddr , record .CodeAddr + record .CodeSize )
324- if err != nil {
325- return fmt .Errorf ("lpm failure %#x/%#x" , record .CodeAddr , record .CodeSize )
326- }
327-
328- for _ , prefix := range prefixes {
329- // TODO: Include FileID
330- err := ebpf .UpdatePidInterpreterMapping (pid , prefix , support .ProgUnwindBEAM , 0 , 0 )
331- if err != nil {
332- return err
333- }
334- }
335-
336- // TODO: remove mappings that have been moved/unloaded
337-
338- default :
339- log .Warnf ("Ignoring JITDump record type %d" , recordHeader .ID )
340- SkipJITDumpRecord (file , recordHeader )
341- }
342- }
343-
344- return nil
345- }
346-
347202func (i * beamInstance ) Detach (interpreter.EbpfHandler , libpf.PID ) error {
348203 log .Infof ("BEAM interpreter detaching" )
349204 return nil
@@ -434,7 +289,6 @@ func (i *beamInstance) findCodeHeader(pc libpf.Address) (codeHeader libpf.Addres
434289 lowIdx = midIdx + 1
435290 } else {
436291 codeHeader = midStart
437- // log.Warnf("BEAM codeHeader[%d] range: 0x%x - 0x%x (%d)", midIdx, midStart, midEnd, midEnd-midStart)
438292 break
439293 }
440294 }
@@ -515,7 +369,6 @@ func (i *beamInstance) findMFA(pc libpf.Address, codeHeader libpf.Address) (func
515369 functionID := i .rm .Uint32 (ertsCodeInfo + libpf .Address (16 + 8 ))
516370 arity := i .rm .Uint32 (ertsCodeInfo + libpf .Address (16 + 16 ))
517371
518- // log.Warnf("BEAM MFA range: 0x%x - 0x%x (%d)", midStart, midEnd, midEnd-midStart)
519372 return functionIndex , moduleID , functionID , arity , nil
520373 }
521374 }
@@ -546,13 +399,10 @@ func (i *beamInstance) findFileLocation(codeHeader libpf.Address, functionIndex
546399 lineLow := i .rm .Ptr (lineTable + libpf .Address (8 * functionIndex + 24 ))
547400 lineHigh := i .rm .Ptr (lineTable + libpf .Address (8 * (functionIndex + 1 )+ 24 ))
548401
549- // log.Warnf("BEAM line range for functionIndex %d: (0x%x - 0x%x)", functionIndex, lineLow, lineHigh)
550-
551402 // We need to align the lineMid values on 8-byte address boundaries
552403 bitmask := libpf .Address (^ (uint64 (0xf )))
553404 for lineHigh > lineLow {
554405 lineMid := lineLow + ((lineHigh - lineLow )/ 2 )& bitmask
555- // log.Warnf("BEAM lineMid: 0x%x, midRange: (0x%x - 0x%x)", lineMid, i.rm.Ptr(lineMid), i.rm.Ptr(lineMid+libpf.Address(8)))
556406
557407 if pc < i .rm .Ptr (lineMid ) {
558408 lineHigh = lineMid
@@ -562,7 +412,6 @@ func (i *beamInstance) findFileLocation(codeHeader libpf.Address, functionIndex
562412 locSize := i .rm .Uint32 (lineTable + libpf .Address (8 ))
563413 locTab := i .rm .Ptr (lineTable + libpf .Address (16 ))
564414 locAddr := locTab + libpf .Address (locSize * locIndex )
565- // log.Warnf("BEAM locIndex: %d, locSize: %d, locAddr: %x", locIndex, locSize, locAddr)
566415 loc := uint64 (0 )
567416 if locSize == 2 {
568417 loc = uint64 (i .rm .Uint16 (locAddr ))
@@ -639,7 +488,6 @@ func (i *beamInstance) readErlangString(eterm libpf.Address, maxLength uint64) s
639488 length ++
640489 nextAddr := libpf .Address ((eterm & ETP_PTR_MASK ) + 8 )
641490 eterm = libpf .Address (i .rm .Uint64 (nextAddr ))
642- // log.Warnf("BEAM charAddr: %x, charValue: %x, char: %c, nextAddr: %x", charAddr, charValue, char, nextAddr)
643491 }
644492
645493 if length > maxLength {
0 commit comments