83 lines
1.9 KiB
Go
83 lines
1.9 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
/*
|
|
* Line tables
|
|
*/
|
|
|
|
package gosym
|
|
|
|
import "encoding/binary"
|
|
|
|
type LineTable struct {
|
|
Data []byte
|
|
PC uint64
|
|
Line int
|
|
}
|
|
|
|
// TODO(rsc): Need to pull in quantum from architecture definition.
|
|
const quantum = 1
|
|
|
|
func (t *LineTable) parse(targetPC uint64, targetLine int) (b []byte, pc uint64, line int) {
|
|
// The PC/line table can be thought of as a sequence of
|
|
// <pc update>* <line update>
|
|
// batches. Each update batch results in a (pc, line) pair,
|
|
// where line applies to every PC from pc up to but not
|
|
// including the pc of the next pair.
|
|
//
|
|
// Here we process each update individually, which simplifies
|
|
// the code, but makes the corner cases more confusing.
|
|
b, pc, line = t.Data, t.PC, t.Line
|
|
for pc <= targetPC && line != targetLine && len(b) > 0 {
|
|
code := b[0]
|
|
b = b[1:]
|
|
switch {
|
|
case code == 0:
|
|
if len(b) < 4 {
|
|
b = b[0:0]
|
|
break
|
|
}
|
|
val := binary.BigEndian.Uint32(b)
|
|
b = b[4:]
|
|
line += int(val)
|
|
case code <= 64:
|
|
line += int(code)
|
|
case code <= 128:
|
|
line -= int(code - 64)
|
|
default:
|
|
pc += quantum * uint64(code-128)
|
|
continue
|
|
}
|
|
pc += quantum
|
|
}
|
|
return b, pc, line
|
|
}
|
|
|
|
func (t *LineTable) slice(pc uint64) *LineTable {
|
|
data, pc, line := t.parse(pc, -1)
|
|
return &LineTable{data, pc, line}
|
|
}
|
|
|
|
func (t *LineTable) PCToLine(pc uint64) int {
|
|
_, _, line := t.parse(pc, -1)
|
|
return line
|
|
}
|
|
|
|
func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 {
|
|
_, pc, line1 := t.parse(maxpc, line)
|
|
if line1 != line {
|
|
return 0
|
|
}
|
|
// Subtract quantum from PC to account for post-line increment
|
|
return pc - quantum
|
|
}
|
|
|
|
// NewLineTable returns a new PC/line table
|
|
// corresponding to the encoded data.
|
|
// Text must be the start address of the
|
|
// corresponding text segment.
|
|
func NewLineTable(data []byte, text uint64) *LineTable {
|
|
return &LineTable{data, text, 0}
|
|
}
|