1
2
3
4
5 6 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
20 const quantum = 1
21
22 func (t *LineTable) parse(targetPC uint64, targetLine int) (b []byte, pc uint64, line int) {
23
24
25
26
27
28
29
30
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
73 return pc - quantum
74 }
75
76
77
78
79
80 func NewLineTable(data []byte, text uint64) *LineTable {
81 return &LineTable{data, text, 0}
82 }