Selaa lähdekoodia

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 vuotta sitten
vanhempi
commit
7098ae611f
No account linked to committer's email address

+ 1
- 0
internal/symbolizer/symbolizer.go Näytä tiedosto

168
 		}
168
 		}
169
 
169
 
170
 		l.Line = make([]profile.Line, len(stack))
170
 		l.Line = make([]profile.Line, len(stack))
171
+		l.IsFolded = false
171
 		for i, frame := range stack {
172
 		for i, frame := range stack {
172
 			if frame.Func != "" {
173
 			if frame.Func != "" {
173
 				m.HasFunctions = true
174
 				m.HasFunctions = true

+ 2
- 0
profile/encode.go Näytä tiedosto

480
 	for i := range p.Line {
480
 	for i := range p.Line {
481
 		encodeMessage(b, 4, &p.Line[i])
481
 		encodeMessage(b, 4, &p.Line[i])
482
 	}
482
 	}
483
+	encodeBoolOpt(b, 5, p.IsFolded)
483
 }
484
 }
484
 
485
 
485
 var locationDecoder = []decoder{
486
 var locationDecoder = []decoder{
493
 		pp.Line = append(pp.Line, Line{})
494
 		pp.Line = append(pp.Line, Line{})
494
 		return decodeMessage(b, &pp.Line[n])
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
 func (p *Line) decoder() []decoder {
500
 func (p *Line) decoder() []decoder {

+ 8
- 5
profile/merge.go Näytä tiedosto

234
 
234
 
235
 	mi := pm.mapMapping(src.Mapping)
235
 	mi := pm.mapMapping(src.Mapping)
236
 	l := &Location{
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
 	for i, ln := range src.Line {
243
 	for i, ln := range src.Line {
243
 		l.Line[i] = pm.mapLine(ln)
244
 		l.Line[i] = pm.mapLine(ln)
258
 // key generates locationKey to be used as a key for maps.
259
 // key generates locationKey to be used as a key for maps.
259
 func (l *Location) key() locationKey {
260
 func (l *Location) key() locationKey {
260
 	key := locationKey{
261
 	key := locationKey{
261
-		addr: l.Address,
262
+		addr:     l.Address,
263
+		isFolded: l.IsFolded,
262
 	}
264
 	}
263
 	if l.Mapping != nil {
265
 	if l.Mapping != nil {
264
 		// Normalizes address to handle address space randomization.
266
 		// Normalizes address to handle address space randomization.
279
 type locationKey struct {
281
 type locationKey struct {
280
 	addr, mappingID uint64
282
 	addr, mappingID uint64
281
 	lines           string
283
 	lines           string
284
+	isFolded        bool
282
 }
285
 }
283
 
286
 
284
 func (pm *profileMerger) mapMapping(src *Mapping) mapInfo {
287
 func (pm *profileMerger) mapMapping(src *Mapping) mapInfo {

+ 8
- 4
profile/profile.go Näytä tiedosto

109
 
109
 
110
 // Location corresponds to Profile.Location
110
 // Location corresponds to Profile.Location
111
 type Location struct {
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
 	mappingIDX uint64
118
 	mappingIDX uint64
118
 }
119
 }
591
 	if m := l.Mapping; m != nil {
592
 	if m := l.Mapping; m != nil {
592
 		locStr = locStr + fmt.Sprintf("M=%d ", m.ID)
593
 		locStr = locStr + fmt.Sprintf("M=%d ", m.ID)
593
 	}
594
 	}
595
+	if l.IsFolded {
596
+		locStr = locStr + "[F] "
597
+	}
594
 	if len(l.Line) == 0 {
598
 	if len(l.Line) == 0 {
595
 		ss = append(ss, locStr)
599
 		ss = append(ss, locStr)
596
 	}
600
 	}

+ 33
- 0
profile/profile_test.go Näytä tiedosto

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
 func TestNumLabelMerge(t *testing.T) {
717
 func TestNumLabelMerge(t *testing.T) {
685
 	for _, tc := range []struct {
718
 	for _, tc := range []struct {
686
 		name          string
719
 		name          string

+ 18
- 0
profile/proto_test.go Näytä tiedosto

52
 	{ID: 1, Name: "func1", SystemName: "func1", Filename: "file1"},
52
 	{ID: 1, Name: "func1", SystemName: "func1", Filename: "file1"},
53
 	{ID: 2, Name: "func2", SystemName: "func2", Filename: "file1"},
53
 	{ID: 2, Name: "func2", SystemName: "func2", Filename: "file1"},
54
 	{ID: 3, Name: "func3", SystemName: "func3", Filename: "file2"},
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
 var testL = []*Location{
59
 var testL = []*Location{
86
 		Mapping: testM[1],
88
 		Mapping: testM[1],
87
 		Address: 12,
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
 var all = &Profile{
109
 var all = &Profile{

+ 12
- 1
proto/profile.proto Näytä tiedosto

1
+// Copyright (c) 2016, Google Inc.
2
+// All rights reserved.
3
+//
4
+////////////////////////////////////////////////////////////////////////////////
5
+
1
 // Profile is a common stacktrace profile format.
6
 // Profile is a common stacktrace profile format.
2
 //
7
 //
3
 // Measurements represented with this format should follow the
8
 // Measurements represented with this format should follow the
151
   // instruction addresses or any integer sequence as ids.
156
   // instruction addresses or any integer sequence as ids.
152
   uint64 id = 1;
157
   uint64 id = 1;
153
   // The id of the corresponding profile.Mapping for this location.
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
   // this profile type.
160
   // this profile type.
156
   uint64 mapping_id = 2;
161
   uint64 mapping_id = 2;
157
   // The instruction address for this location, if available.  It
162
   // The instruction address for this location, if available.  It
168
   //    line[0].function_name == "memcpy"
173
   //    line[0].function_name == "memcpy"
169
   //    line[1].function_name == "printf"
174
   //    line[1].function_name == "printf"
170
   repeated Line line = 4;
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
 message Line {
184
 message Line {