@@ -78,8 +78,7 @@ type luajitInstance struct {
78
78
// In order to symbolize frame n we need to know the caller or frame n+1 so we don't
79
79
// symbolize frame n until symbolize is called fo frame n+1.
80
80
previousFrame * host.Frame
81
-
82
- g2Traces uint16
81
+ g2Traces uint16
83
82
}
84
83
85
84
var (
@@ -125,7 +124,7 @@ func (l *luajitInstance) Detach(ebpf interpreter.EbpfHandler, pid libpf.PID) err
125
124
126
125
func Loader (ebpf interpreter.EbpfHandler , info * interpreter.LoaderInfo ) (interpreter.Data , error ) {
127
126
base := path .Base (info .FileName ())
128
- if ! strings .HasPrefix (base , "libluajit-5.1.so" ) {
127
+ if ! strings .HasPrefix (base , "libluajit-5.1.so" ) && base != "luajit" {
129
128
return nil , nil
130
129
}
131
130
@@ -309,6 +308,9 @@ func (l *luajitInstance) SynchronizeMappings(ebpf interpreter.EbpfHandler,
309
308
newPrefixes = append (newPrefixes , p ... )
310
309
}
311
310
311
+ logf ("lj: new traces detected for pid(%v) added %d new traces with %d prefixes and removed %d prefixes" ,
312
+ pr .PID (), len (traces ), len (newPrefixes ), len (prefixes ))
313
+
312
314
l .prefixesByG [g ] = newPrefixes
313
315
l .traceHashes [g ] = hash
314
316
}
@@ -330,19 +332,25 @@ func (l *luajitInstance) getGCproto(pt libpf.Address) (*proto, error) {
330
332
return gc , nil
331
333
}
332
334
335
+ // symbolizeFrame symbolizes the previous (up the stack)
333
336
func (l * luajitInstance ) symbolizeFrame (symbolReporter reporter.SymbolReporter ,
334
337
funcName string , trace * libpf.Trace ) error {
335
338
if l .previousFrame == nil || l .previousFrame .File == 0 {
336
339
return errors .New ("previous frame not set" )
337
340
}
338
- pt , err := l .getGCproto (libpf .Address (l .previousFrame .File ))
339
- if err != nil {
340
- return err
341
- }
341
+ ptAddr := libpf .Address (l .previousFrame .File )
342
342
pc := uint32 (l .previousFrame .Lineno )
343
- line := pt .getLine (pc )
344
- fileName := pt .getName ()
345
- logf ("lj: [%x] %v+%v at %v:%v" , pt .ptAddr , funcName , pc , fileName , line )
343
+ var line uint32
344
+ var fileName string
345
+ if ptAddr != C .LUAJIT_FFI_FUNC {
346
+ pt , err := l .getGCproto (ptAddr )
347
+ if err != nil {
348
+ return err
349
+ }
350
+ line = pt .getLine (pc )
351
+ fileName = pt .getName ()
352
+ }
353
+ logf ("lj: [%x] %v+%v at %v:%v" , ptAddr , funcName , pc , fileName , line )
346
354
// The fnv hash Write() method calls cannot fail, so it's safe to ignore the errors.
347
355
h := fnv .New128a ()
348
356
_ , _ = h .Write ([]byte (fileName )) //FIXME: needless allocation
@@ -357,6 +365,10 @@ func (l *luajitInstance) symbolizeFrame(symbolReporter reporter.SymbolReporter,
357
365
return nil
358
366
}
359
367
368
+ // Symbolize is a little weird in lua since we need the caller frame to get the name of the
369
+ // function being called. So we stash the info for the current frame and each symbolize call
370
+ // actually symolizes the previous frame. The unwinder emits a special frame with file 0 to
371
+ // indicate the end of the lua stack.
360
372
func (l * luajitInstance ) Symbolize (symbolReporter reporter.SymbolReporter , frame * host.Frame ,
361
373
trace * libpf.Trace ) error {
362
374
if ! frame .Type .IsInterpType (libpf .LuaJIT ) {
@@ -372,18 +384,40 @@ func (l *luajitInstance) Symbolize(symbolReporter reporter.SymbolReporter, frame
372
384
return nil
373
385
}
374
386
375
- ptaddr := libpf .Address (frame .File )
376
- pc := uint32 (frame .Lineno )
377
- pt , err := l .getGCproto (ptaddr )
378
- if err != nil {
379
- return err
380
- }
381
-
382
387
// The function being invoked at this frame (caller) is the name for the previous
383
388
// frame (callee). For the last frame frame.File will be 0 and pt will be nil and funcName
384
- // will be "main".
385
- funcName := pt .getFunctionName (pc )
386
- err = l .symbolizeFrame (symbolReporter , funcName , trace )
389
+ // will be "main". Lua is a real deal dynamic functional language, functions don't have
390
+ // inherent names they are just values.
391
+ var funcName string
392
+ if frame .File == C .LUAJIT_FFI_FUNC {
393
+ switch frame .Lineno & 7 {
394
+ case 1 :
395
+ funcName = "c-frame"
396
+ case 2 :
397
+ funcName = "cont-frame"
398
+ case 3 :
399
+ panic ("unexpected frame type 3" )
400
+ case 4 :
401
+ // FIXME: Not yet understood why an FFI frame would have a lua func attached, probably a bug.
402
+ funcName = "lua-frame"
403
+ case 5 :
404
+ funcName = "cpcall"
405
+ case 6 :
406
+ funcName = "ff-pcall"
407
+ case 7 :
408
+ funcName = "ff-pcall-hook"
409
+ }
410
+ } else {
411
+ ptaddr := libpf .Address (frame .File )
412
+ pc := uint32 (frame .Lineno )
413
+ pt , err := l .getGCproto (ptaddr )
414
+ if err != nil {
415
+ return err
416
+ }
417
+ funcName = pt .getFunctionName (pc )
418
+ }
419
+
420
+ err := l .symbolizeFrame (symbolReporter , funcName , trace )
387
421
388
422
if frame .File == 0 {
389
423
logf ("lj: end LuaJIT frame" )
0 commit comments