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  }