github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/debug/gosym/pclntab.go (about) 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 }