@@ -505,7 +505,121 @@ func main() {
505
505
}
506
506
}
507
507
508
- func TestInlinedRoutineRecords (t * testing.T ) {
508
+ // TestInlinedRoutineCallFileLine tests the call file and line records for an
509
+ // inlined subroutine.
510
+ func TestInlinedRoutineCallFileLine (t * testing.T ) {
511
+ testenv .MustHaveGoBuild (t )
512
+
513
+ if runtime .GOOS == "plan9" {
514
+ t .Skip ("skipping on plan9; no DWARF symbol table in executables" )
515
+ }
516
+
517
+ t .Parallel ()
518
+
519
+ const prog = `
520
+ package main
521
+
522
+ var G int
523
+
524
+ //go:noinline
525
+ func notinlined() int {
526
+ return 42
527
+ }
528
+
529
+ func inlined() int {
530
+ return notinlined()
531
+ }
532
+
533
+ func main() {
534
+ x := inlined()
535
+ G = x
536
+ }
537
+ `
538
+ // Note: this is a build with "-l=4", as opposed to "-l -N". The
539
+ // test is intended to verify DWARF that is only generated when
540
+ // the inliner is active. We're only going to look at the DWARF for
541
+ // main.main, however, hence we build with "-gcflags=-l=4" as opposed
542
+ // to "-gcflags=all=-l=4".
543
+ d , ex := gobuildAndExamine (t , prog , OptInl4 )
544
+
545
+ const (
546
+ callFile = "test.go" // basename
547
+ callLine = 16
548
+ )
549
+
550
+ maindie := findSubprogramDIE (t , ex , "main.main" )
551
+
552
+ // Walk main's children and pick out the inlined subroutines
553
+ mainIdx := ex .IdxFromOffset (maindie .Offset )
554
+ childDies := ex .Children (mainIdx )
555
+ found := false
556
+ for _ , child := range childDies {
557
+ if child .Tag != dwarf .TagInlinedSubroutine {
558
+ continue
559
+ }
560
+
561
+ // Found an inlined subroutine.
562
+ if found {
563
+ t .Fatalf ("Found multiple inlined subroutines, expect only one" )
564
+ }
565
+ found = true
566
+
567
+ // Locate abstract origin.
568
+ ooff , originOK := child .Val (dwarf .AttrAbstractOrigin ).(dwarf.Offset )
569
+ if ! originOK {
570
+ t .Fatalf ("no abstract origin attr for inlined subroutine at offset %v" , child .Offset )
571
+ }
572
+ originDIE := ex .EntryFromOffset (ooff )
573
+ if originDIE == nil {
574
+ t .Fatalf ("can't locate origin DIE at off %v" , ooff )
575
+ }
576
+
577
+ // Name should check out.
578
+ name , ok := originDIE .Val (dwarf .AttrName ).(string )
579
+ if ! ok {
580
+ t .Fatalf ("no name attr for inlined subroutine at offset %v" , child .Offset )
581
+ }
582
+ if name != "main.inlined" {
583
+ t .Fatalf ("expected inlined routine %s got %s" , "main.cand" , name )
584
+ }
585
+
586
+ // Verify that the call_file attribute for the inlined
587
+ // instance is ok. In this case it should match the file
588
+ // for the main routine. To do this we need to locate the
589
+ // compilation unit DIE that encloses what we're looking
590
+ // at; this can be done with the examiner.
591
+ cf , cfOK := child .Val (dwarf .AttrCallFile ).(int64 )
592
+ if ! cfOK {
593
+ t .Fatalf ("no call_file attr for inlined subroutine at offset %v" , child .Offset )
594
+ }
595
+ file , err := ex .FileRef (d , mainIdx , cf )
596
+ if err != nil {
597
+ t .Errorf ("FileRef: %v" , err )
598
+ continue
599
+ }
600
+ base := filepath .Base (file )
601
+ if base != callFile {
602
+ t .Errorf ("bad call_file attribute, found '%s', want '%s'" ,
603
+ file , callFile )
604
+ }
605
+
606
+ // Verify that the call_line attribute for the inlined
607
+ // instance is ok.
608
+ cl , clOK := child .Val (dwarf .AttrCallLine ).(int64 )
609
+ if ! clOK {
610
+ t .Fatalf ("no call_line attr for inlined subroutine at offset %v" , child .Offset )
611
+ }
612
+ if cl != callLine {
613
+ t .Errorf ("bad call_line attribute, found %d, want %d" , cl , callLine )
614
+ }
615
+ }
616
+ if ! found {
617
+ t .Fatalf ("not enough inlined subroutines found in main.main" )
618
+ }
619
+ }
620
+
621
+ // TestInlinedRoutineArgsVars tests the argument and variable records for an inlined subroutine.
622
+ func TestInlinedRoutineArgsVars (t * testing.T ) {
509
623
testenv .MustHaveGoBuild (t )
510
624
511
625
if runtime .GOOS == "plan9" {
@@ -529,112 +643,93 @@ func cand(x, y int) int {
529
643
}
530
644
531
645
func main() {
532
- x := cand(G*G,G|7%G)
533
- G = x
646
+ x := cand(G*G,G|7%G)
647
+ G = x
534
648
}
535
649
`
536
650
// Note: this is a build with "-l=4", as opposed to "-l -N". The
537
651
// test is intended to verify DWARF that is only generated when
538
652
// the inliner is active. We're only going to look at the DWARF for
539
653
// main.main, however, hence we build with "-gcflags=-l=4" as opposed
540
654
// to "-gcflags=all=-l=4".
541
- d , ex := gobuildAndExamine (t , prog , OptInl4 )
542
-
543
- // The inlined subroutines we expect to visit
544
- expectedInl := []string {"main.cand" }
655
+ _ , ex := gobuildAndExamine (t , prog , OptInl4 )
545
656
546
657
maindie := findSubprogramDIE (t , ex , "main.main" )
547
658
548
659
// Walk main's children and pick out the inlined subroutines
549
660
mainIdx := ex .IdxFromOffset (maindie .Offset )
550
661
childDies := ex .Children (mainIdx )
551
- exCount := 0
662
+ found := false
552
663
for _ , child := range childDies {
553
- if child .Tag == dwarf .TagInlinedSubroutine {
554
- // Found an inlined subroutine, locate abstract origin.
555
- ooff , originOK := child .Val (dwarf .AttrAbstractOrigin ).(dwarf.Offset )
556
- if ! originOK {
557
- t .Fatalf ("no abstract origin attr for inlined subroutine at offset %v" , child .Offset )
558
- }
559
- originDIE := ex .EntryFromOffset (ooff )
560
- if originDIE == nil {
561
- t .Fatalf ("can't locate origin DIE at off %v" , ooff )
562
- }
664
+ if child .Tag != dwarf .TagInlinedSubroutine {
665
+ continue
666
+ }
563
667
564
- // Walk the children of the abstract subroutine. We expect
565
- // to see child variables there, even if (perhaps due to
566
- // optimization) there are no references to them from the
567
- // inlined subroutine DIE.
568
- absFcnIdx := ex .IdxFromOffset (ooff )
569
- absFcnChildDies := ex .Children (absFcnIdx )
570
- if len (absFcnChildDies ) != 2 {
571
- t .Fatalf ("expected abstract function: expected 2 children, got %d children" , len (absFcnChildDies ))
572
- }
573
- formalCount := 0
574
- for _ , absChild := range absFcnChildDies {
575
- if absChild .Tag == dwarf .TagFormalParameter {
576
- formalCount += 1
577
- continue
578
- }
579
- t .Fatalf ("abstract function child DIE: expected formal, got %v" , absChild .Tag )
580
- }
581
- if formalCount != 2 {
582
- t .Fatalf ("abstract function DIE: expected 2 formals, got %d" , formalCount )
583
- }
668
+ // Found an inlined subroutine.
669
+ if found {
670
+ t .Fatalf ("Found multiple inlined subroutines, expect only one" )
671
+ }
672
+ found = true
584
673
585
- if exCount >= len (expectedInl ) {
586
- t .Fatalf ("too many inlined subroutines found in main.main" )
587
- }
674
+ // Locate abstract origin.
675
+ ooff , originOK := child .Val (dwarf .AttrAbstractOrigin ).(dwarf.Offset )
676
+ if ! originOK {
677
+ t .Fatalf ("no abstract origin attr for inlined subroutine at offset %v" , child .Offset )
678
+ }
679
+ originDIE := ex .EntryFromOffset (ooff )
680
+ if originDIE == nil {
681
+ t .Fatalf ("can't locate origin DIE at off %v" , ooff )
682
+ }
588
683
589
- // Name should check out.
590
- expected := expectedInl [exCount ]
591
- if name , ok := originDIE .Val (dwarf .AttrName ).(string ); ok {
592
- if name != expected {
593
- t .Fatalf ("expected inlined routine %s got %s" , name , expected )
594
- }
595
- }
596
- exCount ++
597
-
598
- // Verify that the call_file attribute for the inlined
599
- // instance is ok. In this case it should match the file
600
- // for the main routine. To do this we need to locate the
601
- // compilation unit DIE that encloses what we're looking
602
- // at; this can be done with the examiner.
603
- cf , cfOK := child .Val (dwarf .AttrCallFile ).(int64 )
604
- if ! cfOK {
605
- t .Fatalf ("no call_file attr for inlined subroutine at offset %v" , child .Offset )
606
- }
607
- file , err := ex .FileRef (d , mainIdx , cf )
608
- if err != nil {
609
- t .Errorf ("FileRef: %v" , err )
684
+ // Name should check out.
685
+ name , ok := originDIE .Val (dwarf .AttrName ).(string )
686
+ if ! ok {
687
+ t .Fatalf ("no name attr for inlined subroutine at offset %v" , child .Offset )
688
+ }
689
+ if name != "main.cand" {
690
+ t .Fatalf ("expected inlined routine %s got %s" , "main.cand" , name )
691
+ }
692
+
693
+ // Walk the children of the abstract subroutine. We expect
694
+ // to see child variables there, even if (perhaps due to
695
+ // optimization) there are no references to them from the
696
+ // inlined subroutine DIE.
697
+ absFcnIdx := ex .IdxFromOffset (ooff )
698
+ absFcnChildDies := ex .Children (absFcnIdx )
699
+ if len (absFcnChildDies ) != 2 {
700
+ t .Fatalf ("expected abstract function: expected 2 children, got %d children" , len (absFcnChildDies ))
701
+ }
702
+ formalCount := 0
703
+ for _ , absChild := range absFcnChildDies {
704
+ if absChild .Tag == dwarf .TagFormalParameter {
705
+ formalCount += 1
610
706
continue
611
707
}
612
- base := filepath . Base ( file )
613
- if base != "test.go" {
614
- t . Errorf ( "bad call_file attribute, found '%s', want '%s'" ,
615
- file , "test.go" )
616
- }
708
+ t . Fatalf ( "abstract function child DIE: expected formal, got %v" , absChild . Tag )
709
+ }
710
+ if formalCount != 2 {
711
+ t . Fatalf ( "abstract function DIE: expected 2 formals, got %d" , formalCount )
712
+ }
617
713
618
- omap := make (map [dwarf.Offset ]bool )
619
-
620
- // Walk the child variables of the inlined routine. Each
621
- // of them should have a distinct abstract origin-- if two
622
- // vars point to the same origin things are definitely broken.
623
- inlIdx := ex .IdxFromOffset (child .Offset )
624
- inlChildDies := ex .Children (inlIdx )
625
- for _ , k := range inlChildDies {
626
- ooff , originOK := k .Val (dwarf .AttrAbstractOrigin ).(dwarf.Offset )
627
- if ! originOK {
628
- t .Fatalf ("no abstract origin attr for child of inlined subroutine at offset %v" , k .Offset )
629
- }
630
- if _ , found := omap [ooff ]; found {
631
- t .Fatalf ("duplicate abstract origin at child of inlined subroutine at offset %v" , k .Offset )
632
- }
633
- omap [ooff ] = true
714
+ omap := make (map [dwarf.Offset ]bool )
715
+
716
+ // Walk the child variables of the inlined routine. Each
717
+ // of them should have a distinct abstract origin-- if two
718
+ // vars point to the same origin things are definitely broken.
719
+ inlIdx := ex .IdxFromOffset (child .Offset )
720
+ inlChildDies := ex .Children (inlIdx )
721
+ for _ , k := range inlChildDies {
722
+ ooff , originOK := k .Val (dwarf .AttrAbstractOrigin ).(dwarf.Offset )
723
+ if ! originOK {
724
+ t .Fatalf ("no abstract origin attr for child of inlined subroutine at offset %v" , k .Offset )
725
+ }
726
+ if _ , found := omap [ooff ]; found {
727
+ t .Fatalf ("duplicate abstract origin at child of inlined subroutine at offset %v" , k .Offset )
634
728
}
729
+ omap [ooff ] = true
635
730
}
636
731
}
637
- if exCount != len ( expectedInl ) {
732
+ if ! found {
638
733
t .Fatalf ("not enough inlined subroutines found in main.main" )
639
734
}
640
735
}
0 commit comments