@@ -359,7 +359,7 @@ func (i *beamInstance) Symbolize(symbolReporter reporter.SymbolReporter, frame *
359
359
return err
360
360
}
361
361
362
- moduleID , functionID , arity , err := i .findMFA (pc , codeHeader )
362
+ functionIndex , moduleID , functionID , arity , err := i .findMFA (pc , codeHeader )
363
363
if err != nil {
364
364
return err
365
365
}
@@ -382,43 +382,27 @@ func (i *beamInstance) Symbolize(symbolReporter reporter.SymbolReporter, frame *
382
382
mfaName = fmt .Sprintf ("%s:%s/%d" , moduleName , functionName , arity )
383
383
}
384
384
385
- log .Warnf ("BEAM Found function: %s" , mfaName )
385
+ lineNumber := i .findFileLocation (codeHeader , functionIndex , pc )
386
+
387
+ log .Warnf ("BEAM Found function %s at line %d" , mfaName , lineNumber )
386
388
frameID := libpf .NewFrameID (libpf .NewFileID (uint64 (moduleID ), 0x0 ), libpf .AddressOrLineno ((uint64 (functionID )<< 32 )+ uint64 (arity )))
387
389
388
390
symbolReporter .FrameMetadata (& reporter.FrameMetadataArgs {
389
391
FrameID : frameID ,
390
392
FunctionName : mfaName ,
393
+ SourceLine : libpf .SourceLineno (lineNumber ),
391
394
})
392
395
trace .AppendFrameID (libpf .BEAMFrame , frameID )
393
396
394
- //lineTable := i.rm.Ptr(codeHeader + libpf.Address(72))
395
-
396
- // `lineTable` points to a table of `BeamCodeLineTab_` structs:
397
- // https://github.com/erlang/otp/blob/OTP-27.2.4/erts/emulator/beam/beam_code.h#L130-L138
398
- // (gdb) ptype/o $hdr.line_table
399
- // type = const struct BeamCodeLineTab_ {
400
- // 0 | 8 const Eterm *fname_ptr;
401
- // 8 | 4 int loc_size;
402
- // XXX 4-byte hole
403
- // 16 | 8 union {
404
- // 8 Uint16 *p2;
405
- // 8 Uint32 *p4;
406
- // total size (bytes): 8
407
- // } loc_tab;
408
- // 24 | 8 const void **func_tab[1];
409
- //
410
- // total size (bytes): 32
411
397
return nil
412
398
}
413
399
414
- func (i * beamInstance ) findCodeHeader (pc libpf.Address ) (libpf.Address , error ) {
400
+ func (i * beamInstance ) findCodeHeader (pc libpf.Address ) (codeHeader libpf.Address , err error ) {
415
401
// Index into the active static `r` variable using the currently-active code index (the size of the `ranges` struct is 32 bytes)
416
402
// https://github.com/erlang/otp/blob/OTP-27.2.4/erts/emulator/beam/beam_ranges.c#L62
417
403
codeIndex := i .rm .Uint64 (i .codeIndexPtr )
418
404
activeRanges := i .rangesPtr + libpf .Address (32 * codeIndex )
419
405
420
- codeHeader := libpf .Address (0 )
421
-
422
406
// Use offsets into the `ranges` struct to get the beginning of the array and the number of entries based on
423
407
// https://github.com/erlang/otp/blob/OTP-27.2.4/erts/emulator/beam/beam_ranges.c#L56-L61
424
408
modules := i .rm .Ptr (activeRanges )
@@ -443,6 +427,7 @@ func (i *beamInstance) findCodeHeader(pc libpf.Address) (libpf.Address, error) {
443
427
lowIdx = midIdx + 1
444
428
} else {
445
429
codeHeader = midStart
430
+ log .Warnf ("BEAM codeHeader[%d] range: 0x%x - 0x%x (%d)" , midIdx , midStart , midEnd , midEnd - midStart )
446
431
break
447
432
}
448
433
}
@@ -453,7 +438,7 @@ func (i *beamInstance) findCodeHeader(pc libpf.Address) (libpf.Address, error) {
453
438
return codeHeader , nil
454
439
}
455
440
456
- func (i * beamInstance ) findMFA (pc libpf.Address , codeHeader libpf.Address ) (moduleID uint32 , functionID uint32 , arity uint32 , err error ) {
441
+ func (i * beamInstance ) findMFA (pc libpf.Address , codeHeader libpf.Address ) (functionIndex uint64 , moduleID uint32 , functionID uint32 , arity uint32 , err error ) {
457
442
// `codeHeader` points to `BeamCodeHeader` struct, defined here:
458
443
// https://github.com/erlang/otp/blob/OTP-27.2.4/erts/emulator/beam/beam_code.h#L56-L125
459
444
// Need to figure out a better way to maintain offsets for the `functions` field, but for now...
@@ -515,19 +500,73 @@ func (i *beamInstance) findMFA(pc libpf.Address, codeHeader libpf.Address) (modu
515
500
lowIdx = midIdx + 1
516
501
} else {
517
502
ertsCodeInfo = midStart
503
+ functionIndex = midIdx
518
504
519
505
// `mfa` is defined here:
520
506
// https://github.com/erlang/otp/blob/OTP-27.2.4/erts/emulator/beam/code_ix.h#L87-L95
521
507
moduleID := i .rm .Uint32 (ertsCodeInfo + libpf .Address (16 ))
522
508
functionID := i .rm .Uint32 (ertsCodeInfo + libpf .Address (16 + 8 ))
523
509
arity := i .rm .Uint32 (ertsCodeInfo + libpf .Address (16 + 16 ))
524
510
525
- return moduleID , functionID , arity , nil
511
+ log .Warnf ("BEAM MFA range: 0x%x - 0x%x (%d)" , midStart , midEnd , midEnd - midStart )
512
+ return functionIndex , moduleID , functionID , arity , nil
526
513
}
527
514
}
528
515
lowStart := i .rm .Ptr (codeHeader + libpf .Address (136 ))
529
516
highEnd := i .rm .Ptr (codeHeader + libpf .Address (136 + (highIdx + 1 )* 8 ))
530
- return 0 , 0 , 0 , fmt .Errorf ("unable to find the MFA for PC 0x%x in expected code range (0x%x - 0x%x)" , pc , lowStart , highEnd )
517
+ return 0 , 0 , 0 , 0 , fmt .Errorf ("BEAM unable to find the MFA for PC 0x%x in expected code range (0x%x - 0x%x)" , pc , lowStart , highEnd )
518
+ }
519
+
520
+ func (i * beamInstance ) findFileLocation (codeHeader libpf.Address , functionIndex uint64 , pc libpf.Address ) uint64 {
521
+ lineTable := i .rm .Ptr (codeHeader + libpf .Address (72 ))
522
+
523
+ // `lineTable` points to a table of `BeamCodeLineTab_` structs:
524
+ // https://github.com/erlang/otp/blob/OTP-27.2.4/erts/emulator/beam/beam_code.h#L130-L138
525
+ // (gdb) ptype/o $hdr.line_table
526
+ // type = const struct BeamCodeLineTab_ {
527
+ // 0 | 8 const Eterm *fname_ptr;
528
+ // 8 | 4 int loc_size;
529
+ // XXX 4-byte hole
530
+ // 16 | 8 union {
531
+ // 8 Uint16 *p2;
532
+ // 8 Uint32 *p4;
533
+ // total size (bytes): 8
534
+ // } loc_tab;
535
+ // 24 | 8 const void **func_tab[1];
536
+ //
537
+ // total size (bytes): 32
538
+
539
+ lineLow := i .rm .Ptr (lineTable + libpf .Address (8 * functionIndex + 24 ))
540
+ lineHigh := i .rm .Ptr (lineTable + libpf .Address (8 * (functionIndex + 1 )+ 24 ))
541
+
542
+ log .Warnf ("BEAM line range for functionIndex %d: (0x%x - 0x%x)" , functionIndex , lineLow , lineHigh )
543
+
544
+ // We need to align the lineMid values on 8-byte address boundaries
545
+ bitmask := libpf .Address (^ (uint64 (0xf )))
546
+ for lineHigh > lineLow {
547
+ lineMid := lineLow + ((lineHigh - lineLow )/ 2 )& bitmask
548
+ // log.Warnf("BEAM lineMid: 0x%x, midRange: (0x%x - 0x%x)", lineMid, i.rm.Ptr(lineMid), i.rm.Ptr(lineMid+libpf.Address(8)))
549
+
550
+ if pc < i .rm .Ptr (lineMid ) {
551
+ lineHigh = lineMid
552
+ } else if pc < i .rm .Ptr (lineMid + libpf .Address (8 )) {
553
+ funcTab := i .rm .Ptr (lineTable + libpf .Address (24 ))
554
+ locIndex := uint32 ((lineMid - funcTab ) / 8 )
555
+ locSize := i .rm .Uint32 (lineTable + libpf .Address (8 ))
556
+ locTab := i .rm .Ptr (lineTable + libpf .Address (16 ))
557
+ locAddr := locTab + libpf .Address (locSize * locIndex )
558
+ log .Warnf ("BEAM locIndex: %d, locSize: %d, locAddr: %x" , locIndex , locSize , locAddr )
559
+ if locSize == 2 {
560
+ return uint64 (i .rm .Uint16 (locAddr ))
561
+ } else {
562
+ return uint64 (i .rm .Uint32 (locAddr ))
563
+ }
564
+ } else {
565
+ lineLow = lineMid + 8
566
+ }
567
+ }
568
+
569
+ return 0
531
570
}
532
571
533
572
func (i * beamInstance ) lookupAtom (index uint32 ) (string , error ) {
0 commit comments