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