Sfoglia il codice sorgente

Support parsing of is_folded bit (#296)

* Support parsing of is_folded bit

* Include folded bit lin (*Location).string() and in profile mergining

* address comments

* Set IsFolded to false during symbolization when Line is reset

* simplify tests
Margaret Nolan 7 anni fa
parent
commit
7098ae611f
No account linked to committer's email address

+ 1
- 0
internal/symbolizer/symbolizer.go Vedi File

@@ -168,6 +168,7 @@ func doLocalSymbolize(prof *profile.Profile, fast, force bool, obj plugin.ObjToo
168 168
 		}
169 169
 
170 170
 		l.Line = make([]profile.Line, len(stack))
171
+		l.IsFolded = false
171 172
 		for i, frame := range stack {
172 173
 			if frame.Func != "" {
173 174
 				m.HasFunctions = true

+ 2
- 0
profile/encode.go Vedi File

@@ -480,6 +480,7 @@ func (p *Location) encode(b *buffer) {
480 480
 	for i := range p.Line {
481 481
 		encodeMessage(b, 4, &p.Line[i])
482 482
 	}
483
+	encodeBoolOpt(b, 5, p.IsFolded)
483 484
 }
484 485
 
485 486
 var locationDecoder = []decoder{
@@ -493,6 +494,7 @@ var locationDecoder = []decoder{
493 494
 		pp.Line = append(pp.Line, Line{})
494 495
 		return decodeMessage(b, &pp.Line[n])
495 496
 	},
497
+	func(b *buffer, m message) error { return decodeBool(b, &m.(*Location).IsFolded) }, // optional bool is_folded = 5;
496 498
 }
497 499
 
498 500
 func (p *Line) decoder() []decoder {

+ 8
- 5
profile/merge.go Vedi File

@@ -234,10 +234,11 @@ func (pm *profileMerger) mapLocation(src *Location) *Location {
234 234
 
235 235
 	mi := pm.mapMapping(src.Mapping)
236 236
 	l := &Location{
237
-		ID:      uint64(len(pm.p.Location) + 1),
238
-		Mapping: mi.m,
239
-		Address: uint64(int64(src.Address) + mi.offset),
240
-		Line:    make([]Line, len(src.Line)),
237
+		ID:       uint64(len(pm.p.Location) + 1),
238
+		Mapping:  mi.m,
239
+		Address:  uint64(int64(src.Address) + mi.offset),
240
+		Line:     make([]Line, len(src.Line)),
241
+		IsFolded: src.IsFolded,
241 242
 	}
242 243
 	for i, ln := range src.Line {
243 244
 		l.Line[i] = pm.mapLine(ln)
@@ -258,7 +259,8 @@ func (pm *profileMerger) mapLocation(src *Location) *Location {
258 259
 // key generates locationKey to be used as a key for maps.
259 260
 func (l *Location) key() locationKey {
260 261
 	key := locationKey{
261
-		addr: l.Address,
262
+		addr:     l.Address,
263
+		isFolded: l.IsFolded,
262 264
 	}
263 265
 	if l.Mapping != nil {
264 266
 		// Normalizes address to handle address space randomization.
@@ -279,6 +281,7 @@ func (l *Location) key() locationKey {
279 281
 type locationKey struct {
280 282
 	addr, mappingID uint64
281 283
 	lines           string
284
+	isFolded        bool
282 285
 }
283 286
 
284 287
 func (pm *profileMerger) mapMapping(src *Mapping) mapInfo {

+ 8
- 4
profile/profile.go Vedi File

@@ -109,10 +109,11 @@ type Mapping struct {
109 109
 
110 110
 // Location corresponds to Profile.Location
111 111
 type Location struct {
112
-	ID      uint64
113
-	Mapping *Mapping
114
-	Address uint64
115
-	Line    []Line
112
+	ID       uint64
113
+	Mapping  *Mapping
114
+	Address  uint64
115
+	Line     []Line
116
+	IsFolded bool
116 117
 
117 118
 	mappingIDX uint64
118 119
 }
@@ -591,6 +592,9 @@ func (l *Location) string() string {
591 592
 	if m := l.Mapping; m != nil {
592 593
 		locStr = locStr + fmt.Sprintf("M=%d ", m.ID)
593 594
 	}
595
+	if l.IsFolded {
596
+		locStr = locStr + "[F] "
597
+	}
594 598
 	if len(l.Line) == 0 {
595 599
 		ss = append(ss, locStr)
596 600
 	}

+ 33
- 0
profile/profile_test.go Vedi File

@@ -681,6 +681,39 @@ func TestMergeAll(t *testing.T) {
681 681
 	}
682 682
 }
683 683
 
684
+func TestIsFoldedMerge(t *testing.T) {
685
+	testProfile1Folded := testProfile1.Copy()
686
+	testProfile1Folded.Location[0].IsFolded = true
687
+	testProfile1Folded.Location[1].IsFolded = true
688
+
689
+	for _, tc := range []struct {
690
+		name            string
691
+		profs           []*Profile
692
+		wantLocationLen int
693
+	}{
694
+		{
695
+			name:            "folded and non-folded locations not merged",
696
+			profs:           []*Profile{testProfile1.Copy(), testProfile1Folded.Copy()},
697
+			wantLocationLen: 7,
698
+		},
699
+		{
700
+			name:            "identical folded locations are merged",
701
+			profs:           []*Profile{testProfile1Folded.Copy(), testProfile1Folded.Copy()},
702
+			wantLocationLen: 5,
703
+		},
704
+	} {
705
+		t.Run(tc.name, func(t *testing.T) {
706
+			prof, err := Merge(tc.profs)
707
+			if err != nil {
708
+				t.Fatalf("merge error: %v", err)
709
+			}
710
+			if got, want := len(prof.Location), tc.wantLocationLen; got != want {
711
+				t.Fatalf("got %d locations, want %d locations", got, want)
712
+			}
713
+		})
714
+	}
715
+}
716
+
684 717
 func TestNumLabelMerge(t *testing.T) {
685 718
 	for _, tc := range []struct {
686 719
 		name          string

+ 18
- 0
profile/proto_test.go Vedi File

@@ -52,6 +52,8 @@ var testF = []*Function{
52 52
 	{ID: 1, Name: "func1", SystemName: "func1", Filename: "file1"},
53 53
 	{ID: 2, Name: "func2", SystemName: "func2", Filename: "file1"},
54 54
 	{ID: 3, Name: "func3", SystemName: "func3", Filename: "file2"},
55
+	{ID: 4, Name: "func4", SystemName: "func4", Filename: "file3"},
56
+	{ID: 5, Name: "func5", SystemName: "func5", Filename: "file4"},
55 57
 }
56 58
 
57 59
 var testL = []*Location{
@@ -86,6 +88,22 @@ var testL = []*Location{
86 88
 		Mapping: testM[1],
87 89
 		Address: 12,
88 90
 	},
91
+	{
92
+		ID:      4,
93
+		Mapping: testM[1],
94
+		Address: 12,
95
+		Line: []Line{
96
+			{
97
+				Function: testF[4],
98
+				Line:     6,
99
+			},
100
+			{
101
+				Function: testF[4],
102
+				Line:     6,
103
+			},
104
+		},
105
+		IsFolded: true,
106
+	},
89 107
 }
90 108
 
91 109
 var all = &Profile{

+ 12
- 1
proto/profile.proto Vedi File

@@ -1,3 +1,8 @@
1
+// Copyright (c) 2016, Google Inc.
2
+// All rights reserved.
3
+//
4
+////////////////////////////////////////////////////////////////////////////////
5
+
1 6
 // Profile is a common stacktrace profile format.
2 7
 //
3 8
 // Measurements represented with this format should follow the
@@ -151,7 +156,7 @@ message Location {
151 156
   // instruction addresses or any integer sequence as ids.
152 157
   uint64 id = 1;
153 158
   // The id of the corresponding profile.Mapping for this location.
154
-  // If can be unset if the mapping is unknown or not applicable for
159
+  // It can be unset if the mapping is unknown or not applicable for
155 160
   // this profile type.
156 161
   uint64 mapping_id = 2;
157 162
   // The instruction address for this location, if available.  It
@@ -168,6 +173,12 @@ message Location {
168 173
   //    line[0].function_name == "memcpy"
169 174
   //    line[1].function_name == "printf"
170 175
   repeated Line line = 4;
176
+  // Provides an indication that multiple symbols map to this location's
177
+  // address, for example due to identical code folding by the linker. In that
178
+  // case the line information above represents one of the multiple
179
+  // symbols. This field must be recomputed when the symbolization state of the
180
+  // profile changes.
181
+  bool is_folded = 5;
171 182
 }
172 183
 
173 184
 message Line {