Source file src/pkg/debug/gosym/pclntab.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 /*
6 * Line tables
7 */
8
9 package gosym
10
11 import "encoding/binary"
12
13 type LineTable struct {
14 Data []byte
15 PC uint64
16 Line int
17 }
18
19 // TODO(rsc): Need to pull in quantum from architecture definition.
20 const quantum = 1
21
22 func (t *LineTable) parse(targetPC uint64, targetLine int) (b []byte, pc uint64, line int) {
23 // The PC/line table can be thought of as a sequence of
24 // <pc update>* <line update>
25 // batches. Each update batch results in a (pc, line) pair,
26 // where line applies to every PC from pc up to but not
27 // including the pc of the next pair.
28 //
29 // Here we process each update individually, which simplifies
30 // the code, but makes the corner cases more confusing.
31 b, pc, line = t.Data, t.PC, t.Line
32 for pc <= targetPC && line != targetLine && len(b) > 0 {
33 code := b[0]
34 b = b[1:]
35 switch {
36 case code == 0:
37 if len(b) < 4 {
38 b = b[0:0]
39 break
40 }
41 val := binary.BigEndian.Uint32(b)
42 b = b[4:]
43 line += int(val)
44 case code <= 64:
45 line += int(code)
46 case code <= 128:
47 line -= int(code - 64)
48 default:
49 pc += quantum * uint64(code-128)
50 continue
51 }
52 pc += quantum
53 }
54 return b, pc, line
55 }
56
57 func (t *LineTable) slice(pc uint64) *LineTable {
58 data, pc, line := t.parse(pc, -1)
59 return &LineTable{data, pc, line}
60 }
61
62 func (t *LineTable) PCToLine(pc uint64) int {
63 _, _, line := t.parse(pc, -1)
64 return line
65 }
66
67 func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 {
68 _, pc, line1 := t.parse(maxpc, line)
69 if line1 != line {
70 return 0
71 }
72 // Subtract quantum from PC to account for post-line increment
73 return pc - quantum
74 }
75
76 // NewLineTable returns a new PC/line table
77 // corresponding to the encoded data.
78 // Text must be the start address of the
79 // corresponding text segment.
80 func NewLineTable(data []byte, text uint64) *LineTable {
81 return &LineTable{data, text, 0}
82 }