// 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 // * // 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} }