1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package profile
16
17 import (
18 "errors"
19 "sort"
20 "strings"
21 )
22
23 func (p *Profile) decoder() []decoder {
24 return profileDecoder
25 }
26
27
28
29
30 func (p *Profile) preEncode() {
31 strings := make(map[string]int)
32 addString(strings, "")
33
34 for _, st := range p.SampleType {
35 st.typeX = addString(strings, st.Type)
36 st.unitX = addString(strings, st.Unit)
37 }
38
39 for _, s := range p.Sample {
40 s.labelX = nil
41 var keys []string
42 for k := range s.Label {
43 keys = append(keys, k)
44 }
45 sort.Strings(keys)
46 for _, k := range keys {
47 vs := s.Label[k]
48 for _, v := range vs {
49 s.labelX = append(s.labelX,
50 label{
51 keyX: addString(strings, k),
52 strX: addString(strings, v),
53 },
54 )
55 }
56 }
57 var numKeys []string
58 for k := range s.NumLabel {
59 numKeys = append(numKeys, k)
60 }
61 sort.Strings(numKeys)
62 for _, k := range numKeys {
63 keyX := addString(strings, k)
64 vs := s.NumLabel[k]
65 units := s.NumUnit[k]
66 for i, v := range vs {
67 var unitX int64
68 if len(units) != 0 {
69 unitX = addString(strings, units[i])
70 }
71 s.labelX = append(s.labelX,
72 label{
73 keyX: keyX,
74 numX: v,
75 unitX: unitX,
76 },
77 )
78 }
79 }
80 s.locationIDX = make([]uint64, len(s.Location))
81 for i, loc := range s.Location {
82 s.locationIDX[i] = loc.ID
83 }
84 }
85
86 for _, m := range p.Mapping {
87 m.fileX = addString(strings, m.File)
88 m.buildIDX = addString(strings, m.BuildID)
89 }
90
91 for _, l := range p.Location {
92 for i, ln := range l.Line {
93 if ln.Function != nil {
94 l.Line[i].functionIDX = ln.Function.ID
95 } else {
96 l.Line[i].functionIDX = 0
97 }
98 }
99 if l.Mapping != nil {
100 l.mappingIDX = l.Mapping.ID
101 } else {
102 l.mappingIDX = 0
103 }
104 }
105 for _, f := range p.Function {
106 f.nameX = addString(strings, f.Name)
107 f.systemNameX = addString(strings, f.SystemName)
108 f.filenameX = addString(strings, f.Filename)
109 }
110
111 p.dropFramesX = addString(strings, p.DropFrames)
112 p.keepFramesX = addString(strings, p.KeepFrames)
113
114 if pt := p.PeriodType; pt != nil {
115 pt.typeX = addString(strings, pt.Type)
116 pt.unitX = addString(strings, pt.Unit)
117 }
118
119 p.commentX = nil
120 for _, c := range p.Comments {
121 p.commentX = append(p.commentX, addString(strings, c))
122 }
123
124 p.defaultSampleTypeX = addString(strings, p.DefaultSampleType)
125
126 p.stringTable = make([]string, len(strings))
127 for s, i := range strings {
128 p.stringTable[i] = s
129 }
130 }
131
132 func (p *Profile) encode(b *buffer) {
133 for _, x := range p.SampleType {
134 encodeMessage(b, 1, x)
135 }
136 for _, x := range p.Sample {
137 encodeMessage(b, 2, x)
138 }
139 for _, x := range p.Mapping {
140 encodeMessage(b, 3, x)
141 }
142 for _, x := range p.Location {
143 encodeMessage(b, 4, x)
144 }
145 for _, x := range p.Function {
146 encodeMessage(b, 5, x)
147 }
148 encodeStrings(b, 6, p.stringTable)
149 encodeInt64Opt(b, 7, p.dropFramesX)
150 encodeInt64Opt(b, 8, p.keepFramesX)
151 encodeInt64Opt(b, 9, p.TimeNanos)
152 encodeInt64Opt(b, 10, p.DurationNanos)
153 if pt := p.PeriodType; pt != nil && (pt.typeX != 0 || pt.unitX != 0) {
154 encodeMessage(b, 11, p.PeriodType)
155 }
156 encodeInt64Opt(b, 12, p.Period)
157 encodeInt64s(b, 13, p.commentX)
158 encodeInt64(b, 14, p.defaultSampleTypeX)
159 }
160
161 var profileDecoder = []decoder{
162 nil,
163
164 func(b *buffer, m message) error {
165 x := new(ValueType)
166 pp := m.(*Profile)
167 pp.SampleType = append(pp.SampleType, x)
168 return decodeMessage(b, x)
169 },
170
171 func(b *buffer, m message) error {
172 x := new(Sample)
173 pp := m.(*Profile)
174 pp.Sample = append(pp.Sample, x)
175 return decodeMessage(b, x)
176 },
177
178 func(b *buffer, m message) error {
179 x := new(Mapping)
180 pp := m.(*Profile)
181 pp.Mapping = append(pp.Mapping, x)
182 return decodeMessage(b, x)
183 },
184
185 func(b *buffer, m message) error {
186 x := new(Location)
187 x.Line = b.tmpLines[:0]
188 pp := m.(*Profile)
189 pp.Location = append(pp.Location, x)
190 err := decodeMessage(b, x)
191 b.tmpLines = x.Line[:0]
192
193 x.Line = append([]Line(nil), x.Line...)
194 return err
195 },
196
197 func(b *buffer, m message) error {
198 x := new(Function)
199 pp := m.(*Profile)
200 pp.Function = append(pp.Function, x)
201 return decodeMessage(b, x)
202 },
203
204 func(b *buffer, m message) error {
205 err := decodeStrings(b, &m.(*Profile).stringTable)
206 if err != nil {
207 return err
208 }
209 if m.(*Profile).stringTable[0] != "" {
210 return errors.New("string_table[0] must be ''")
211 }
212 return nil
213 },
214
215 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).dropFramesX) },
216
217 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).keepFramesX) },
218
219 func(b *buffer, m message) error {
220 if m.(*Profile).TimeNanos != 0 {
221 return errConcatProfile
222 }
223 return decodeInt64(b, &m.(*Profile).TimeNanos)
224 },
225
226 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).DurationNanos) },
227
228 func(b *buffer, m message) error {
229 x := new(ValueType)
230 pp := m.(*Profile)
231 pp.PeriodType = x
232 return decodeMessage(b, x)
233 },
234
235 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).Period) },
236
237 func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Profile).commentX) },
238
239 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).defaultSampleTypeX) },
240 }
241
242
243
244
245 func (p *Profile) postDecode() error {
246 var err error
247 mappings := make(map[uint64]*Mapping, len(p.Mapping))
248 mappingIds := make([]*Mapping, len(p.Mapping)+1)
249 for _, m := range p.Mapping {
250 m.File, err = getString(p.stringTable, &m.fileX, err)
251 m.BuildID, err = getString(p.stringTable, &m.buildIDX, err)
252 if m.ID < uint64(len(mappingIds)) {
253 mappingIds[m.ID] = m
254 } else {
255 mappings[m.ID] = m
256 }
257
258
259
260
261 const prefix = "[kernel.kallsyms]"
262 if strings.HasPrefix(m.File, prefix) {
263 m.KernelRelocationSymbol = m.File[len(prefix):]
264 }
265 }
266
267 functions := make(map[uint64]*Function, len(p.Function))
268 functionIds := make([]*Function, len(p.Function)+1)
269 for _, f := range p.Function {
270 f.Name, err = getString(p.stringTable, &f.nameX, err)
271 f.SystemName, err = getString(p.stringTable, &f.systemNameX, err)
272 f.Filename, err = getString(p.stringTable, &f.filenameX, err)
273 if f.ID < uint64(len(functionIds)) {
274 functionIds[f.ID] = f
275 } else {
276 functions[f.ID] = f
277 }
278 }
279
280 locations := make(map[uint64]*Location, len(p.Location))
281 locationIds := make([]*Location, len(p.Location)+1)
282 for _, l := range p.Location {
283 if id := l.mappingIDX; id < uint64(len(mappingIds)) {
284 l.Mapping = mappingIds[id]
285 } else {
286 l.Mapping = mappings[id]
287 }
288 l.mappingIDX = 0
289 for i, ln := range l.Line {
290 if id := ln.functionIDX; id != 0 {
291 l.Line[i].functionIDX = 0
292 if id < uint64(len(functionIds)) {
293 l.Line[i].Function = functionIds[id]
294 } else {
295 l.Line[i].Function = functions[id]
296 }
297 }
298 }
299 if l.ID < uint64(len(locationIds)) {
300 locationIds[l.ID] = l
301 } else {
302 locations[l.ID] = l
303 }
304 }
305
306 for _, st := range p.SampleType {
307 st.Type, err = getString(p.stringTable, &st.typeX, err)
308 st.Unit, err = getString(p.stringTable, &st.unitX, err)
309 }
310
311
312 numLocations := 0
313 for _, s := range p.Sample {
314 numLocations += len(s.locationIDX)
315 }
316 locBuffer := make([]*Location, numLocations)
317
318 for _, s := range p.Sample {
319 if len(s.labelX) > 0 {
320 labels := make(map[string][]string, len(s.labelX))
321 numLabels := make(map[string][]int64, len(s.labelX))
322 numUnits := make(map[string][]string, len(s.labelX))
323 for _, l := range s.labelX {
324 var key, value string
325 key, err = getString(p.stringTable, &l.keyX, err)
326 if l.strX != 0 {
327 value, err = getString(p.stringTable, &l.strX, err)
328 labels[key] = append(labels[key], value)
329 } else if l.numX != 0 || l.unitX != 0 {
330 numValues := numLabels[key]
331 units := numUnits[key]
332 if l.unitX != 0 {
333 var unit string
334 unit, err = getString(p.stringTable, &l.unitX, err)
335 units = padStringArray(units, len(numValues))
336 numUnits[key] = append(units, unit)
337 }
338 numLabels[key] = append(numLabels[key], l.numX)
339 }
340 }
341 if len(labels) > 0 {
342 s.Label = labels
343 }
344 if len(numLabels) > 0 {
345 s.NumLabel = numLabels
346 for key, units := range numUnits {
347 if len(units) > 0 {
348 numUnits[key] = padStringArray(units, len(numLabels[key]))
349 }
350 }
351 s.NumUnit = numUnits
352 }
353 }
354
355 s.Location = locBuffer[:len(s.locationIDX)]
356 locBuffer = locBuffer[len(s.locationIDX):]
357 for i, lid := range s.locationIDX {
358 if lid < uint64(len(locationIds)) {
359 s.Location[i] = locationIds[lid]
360 } else {
361 s.Location[i] = locations[lid]
362 }
363 }
364 s.locationIDX = nil
365 }
366
367 p.DropFrames, err = getString(p.stringTable, &p.dropFramesX, err)
368 p.KeepFrames, err = getString(p.stringTable, &p.keepFramesX, err)
369
370 if pt := p.PeriodType; pt == nil {
371 p.PeriodType = &ValueType{}
372 }
373
374 if pt := p.PeriodType; pt != nil {
375 pt.Type, err = getString(p.stringTable, &pt.typeX, err)
376 pt.Unit, err = getString(p.stringTable, &pt.unitX, err)
377 }
378
379 for _, i := range p.commentX {
380 var c string
381 c, err = getString(p.stringTable, &i, err)
382 p.Comments = append(p.Comments, c)
383 }
384
385 p.commentX = nil
386 p.DefaultSampleType, err = getString(p.stringTable, &p.defaultSampleTypeX, err)
387 p.stringTable = nil
388 return err
389 }
390
391
392
393 func padStringArray(arr []string, l int) []string {
394 if l <= len(arr) {
395 return arr
396 }
397 return append(arr, make([]string, l-len(arr))...)
398 }
399
400 func (p *ValueType) decoder() []decoder {
401 return valueTypeDecoder
402 }
403
404 func (p *ValueType) encode(b *buffer) {
405 encodeInt64Opt(b, 1, p.typeX)
406 encodeInt64Opt(b, 2, p.unitX)
407 }
408
409 var valueTypeDecoder = []decoder{
410 nil,
411
412 func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).typeX) },
413
414 func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).unitX) },
415 }
416
417 func (p *Sample) decoder() []decoder {
418 return sampleDecoder
419 }
420
421 func (p *Sample) encode(b *buffer) {
422 encodeUint64s(b, 1, p.locationIDX)
423 encodeInt64s(b, 2, p.Value)
424 for _, x := range p.labelX {
425 encodeMessage(b, 3, x)
426 }
427 }
428
429 var sampleDecoder = []decoder{
430 nil,
431
432 func(b *buffer, m message) error { return decodeUint64s(b, &m.(*Sample).locationIDX) },
433
434 func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Sample).Value) },
435
436 func(b *buffer, m message) error {
437 s := m.(*Sample)
438 n := len(s.labelX)
439 s.labelX = append(s.labelX, label{})
440 return decodeMessage(b, &s.labelX[n])
441 },
442 }
443
444 func (p label) decoder() []decoder {
445 return labelDecoder
446 }
447
448 func (p label) encode(b *buffer) {
449 encodeInt64Opt(b, 1, p.keyX)
450 encodeInt64Opt(b, 2, p.strX)
451 encodeInt64Opt(b, 3, p.numX)
452 encodeInt64Opt(b, 4, p.unitX)
453 }
454
455 var labelDecoder = []decoder{
456 nil,
457
458 func(b *buffer, m message) error { return decodeInt64(b, &m.(*label).keyX) },
459
460 func(b *buffer, m message) error { return decodeInt64(b, &m.(*label).strX) },
461
462 func(b *buffer, m message) error { return decodeInt64(b, &m.(*label).numX) },
463
464 func(b *buffer, m message) error { return decodeInt64(b, &m.(*label).unitX) },
465 }
466
467 func (p *Mapping) decoder() []decoder {
468 return mappingDecoder
469 }
470
471 func (p *Mapping) encode(b *buffer) {
472 encodeUint64Opt(b, 1, p.ID)
473 encodeUint64Opt(b, 2, p.Start)
474 encodeUint64Opt(b, 3, p.Limit)
475 encodeUint64Opt(b, 4, p.Offset)
476 encodeInt64Opt(b, 5, p.fileX)
477 encodeInt64Opt(b, 6, p.buildIDX)
478 encodeBoolOpt(b, 7, p.HasFunctions)
479 encodeBoolOpt(b, 8, p.HasFilenames)
480 encodeBoolOpt(b, 9, p.HasLineNumbers)
481 encodeBoolOpt(b, 10, p.HasInlineFrames)
482 }
483
484 var mappingDecoder = []decoder{
485 nil,
486 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).ID) },
487 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Start) },
488 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Limit) },
489 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Offset) },
490 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).fileX) },
491 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).buildIDX) },
492 func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFunctions) },
493 func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFilenames) },
494 func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasLineNumbers) },
495 func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasInlineFrames) },
496 }
497
498 func (p *Location) decoder() []decoder {
499 return locationDecoder
500 }
501
502 func (p *Location) encode(b *buffer) {
503 encodeUint64Opt(b, 1, p.ID)
504 encodeUint64Opt(b, 2, p.mappingIDX)
505 encodeUint64Opt(b, 3, p.Address)
506 for i := range p.Line {
507 encodeMessage(b, 4, &p.Line[i])
508 }
509 encodeBoolOpt(b, 5, p.IsFolded)
510 }
511
512 var locationDecoder = []decoder{
513 nil,
514 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).ID) },
515 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).mappingIDX) },
516 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).Address) },
517 func(b *buffer, m message) error {
518 pp := m.(*Location)
519 n := len(pp.Line)
520 pp.Line = append(pp.Line, Line{})
521 return decodeMessage(b, &pp.Line[n])
522 },
523 func(b *buffer, m message) error { return decodeBool(b, &m.(*Location).IsFolded) },
524 }
525
526 func (p *Line) decoder() []decoder {
527 return lineDecoder
528 }
529
530 func (p *Line) encode(b *buffer) {
531 encodeUint64Opt(b, 1, p.functionIDX)
532 encodeInt64Opt(b, 2, p.Line)
533 encodeInt64Opt(b, 3, p.Column)
534 }
535
536 var lineDecoder = []decoder{
537 nil,
538
539 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Line).functionIDX) },
540
541 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Line) },
542
543 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Column) },
544 }
545
546 func (p *Function) decoder() []decoder {
547 return functionDecoder
548 }
549
550 func (p *Function) encode(b *buffer) {
551 encodeUint64Opt(b, 1, p.ID)
552 encodeInt64Opt(b, 2, p.nameX)
553 encodeInt64Opt(b, 3, p.systemNameX)
554 encodeInt64Opt(b, 4, p.filenameX)
555 encodeInt64Opt(b, 5, p.StartLine)
556 }
557
558 var functionDecoder = []decoder{
559 nil,
560
561 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Function).ID) },
562
563 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).nameX) },
564
565 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).systemNameX) },
566
567 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).filenameX) },
568
569 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).StartLine) },
570 }
571
572 func addString(strings map[string]int, s string) int64 {
573 i, ok := strings[s]
574 if !ok {
575 i = len(strings)
576 strings[s] = i
577 }
578 return int64(i)
579 }
580
581 func getString(strings []string, strng *int64, err error) (string, error) {
582 if err != nil {
583 return "", err
584 }
585 s := int(*strng)
586 if s < 0 || s >= len(strings) {
587 return "", errMalformed
588 }
589 *strng = 0
590 return strings[s], nil
591 }
592
View as plain text