aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8.1/libgo/go/debug/dwarf/line.go
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8.1/libgo/go/debug/dwarf/line.go')
-rw-r--r--gcc-4.8.1/libgo/go/debug/dwarf/line.go481
1 files changed, 0 insertions, 481 deletions
diff --git a/gcc-4.8.1/libgo/go/debug/dwarf/line.go b/gcc-4.8.1/libgo/go/debug/dwarf/line.go
deleted file mode 100644
index 3ab2f2b30..000000000
--- a/gcc-4.8.1/libgo/go/debug/dwarf/line.go
+++ /dev/null
@@ -1,481 +0,0 @@
-// Copyright 2012 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.
-
-// DWARF line number information.
-
-package dwarf
-
-import (
- "errors"
- "path/filepath"
- "sort"
- "strconv"
-)
-
-// A Line holds all the available information about the source code
-// corresponding to a specific program counter address.
-type Line struct {
- Filename string // source file name
- OpIndex int // index of operation in VLIW instruction
- Line int // line number
- Column int // column number
- ISA int // instruction set code
- Discriminator int // block discriminator
- Stmt bool // instruction starts statement
- Block bool // instruction starts basic block
- EndPrologue bool // instruction ends function prologue
- BeginEpilogue bool // instruction begins function epilogue
-}
-
-// LineForPc returns the line number information for a program counter
-// address, if any. When this returns multiple Line structures in a
-// context where only one can be used, the last one is the best.
-func (d *Data) LineForPC(pc uint64) ([]*Line, error) {
- for i := range d.unit {
- u := &d.unit[i]
- if u.pc == nil {
- if err := d.readUnitLine(i, u); err != nil {
- return nil, err
- }
- }
- for _, ar := range u.pc {
- if pc >= ar.low && pc < ar.high {
- return d.findLine(u, pc)
- }
- }
- }
- return nil, nil
-}
-
-// readUnitLine reads in the line number information for a compilation
-// unit.
-func (d *Data) readUnitLine(i int, u *unit) error {
- r := d.unitReader(i)
- setLineOff := false
- for {
- e, err := r.Next()
- if err != nil {
- return err
- }
- if e == nil {
- break
- }
- if r.unit != i {
- break
- }
- switch e.Tag {
- case TagCompileUnit, TagSubprogram, TagEntryPoint, TagInlinedSubroutine:
- low, lowok := e.Val(AttrLowpc).(uint64)
- var high uint64
- var highok bool
- switch v := e.Val(AttrHighpc).(type) {
- case uint64:
- high = v
- highok = true
- case int64:
- high = low + uint64(v)
- highok = true
- }
- if lowok && highok {
- u.pc = append(u.pc, addrRange{low, high})
- } else if off, ok := e.Val(AttrRanges).(Offset); ok {
- if err := d.readAddressRanges(off, low, u); err != nil {
- return err
- }
- }
- val := e.Val(AttrStmtList)
- if val != nil {
- if off, ok := val.(int64); ok {
- u.lineoff = Offset(off)
- setLineOff = true
- } else if off, ok := val.(Offset); ok {
- u.lineoff = off
- setLineOff = true
- } else {
- return errors.New("unrecognized format for DW_ATTR_stmt_list")
- }
- }
- if dir, ok := e.Val(AttrCompDir).(string); ok {
- u.dir = dir
- }
- }
- }
- if !setLineOff {
- u.lineoff = Offset(0)
- u.lineoff--
- }
- return nil
-}
-
-// readAddressRanges adds address ranges to a unit.
-func (d *Data) readAddressRanges(off Offset, base uint64, u *unit) error {
- b := makeBuf(d, u, "ranges", off, d.ranges[off:])
- var highest uint64
- switch u.addrsize {
- case 1:
- highest = 0xff
- case 2:
- highest = 0xffff
- case 4:
- highest = 0xffffffff
- case 8:
- highest = 0xffffffffffffffff
- default:
- return errors.New("unknown address size")
- }
- for {
- if b.err != nil {
- return b.err
- }
- low := b.addr()
- high := b.addr()
- if low == 0 && high == 0 {
- return b.err
- } else if low == highest {
- base = high
- } else {
- u.pc = append(u.pc, addrRange{low + base, high + base})
- }
- }
-}
-
-// findLine finds the line information for a PC value, given the unit
-// containing the information.
-func (d *Data) findLine(u *unit, pc uint64) ([]*Line, error) {
- if u.lines == nil {
- if err := d.parseLine(u); err != nil {
- return nil, err
- }
- }
-
- for _, ln := range u.lines {
- if pc < ln.addrs[0].pc || pc > ln.addrs[len(ln.addrs)-1].pc {
- continue
- }
- i := sort.Search(len(ln.addrs),
- func(i int) bool { return ln.addrs[i].pc > pc })
- i--
- p := new(Line)
- *p = ln.line
- p.Line = ln.addrs[i].line
- ret := []*Line{p}
- for i++; i < len(ln.addrs) && ln.addrs[i].pc == pc; i++ {
- p = new(Line)
- *p = ln.line
- p.Line = ln.addrs[i].line
- ret = append(ret, p)
- }
- return ret, nil
- }
-
- return nil, nil
-}
-
-// FileLine returns the file name and line number for a program
-// counter address, or "", 0 if unknown.
-func (d *Data) FileLine(pc uint64) (string, int, error) {
- r, err := d.LineForPC(pc)
- if err != nil {
- return "", 0, err
- }
- if r == nil {
- return "", 0, nil
- }
- ln := r[len(r)-1]
- return ln.Filename, ln.Line, nil
-}
-
-// A mapLineInfo holds the PC values and line numbers associated with
-// a single Line structure. This representation is chosen to reduce
-// memory usage based on typical debug info.
-type mapLineInfo struct {
- line Line // line.Line will be zero
- addrs lineAddrs // sorted by PC
-}
-
-// A list of lines. This will be sorted by PC.
-type lineAddrs []oneLineInfo
-
-func (p lineAddrs) Len() int { return len(p) }
-func (p lineAddrs) Less(i, j int) bool { return p[i].pc < p[j].pc }
-func (p lineAddrs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
-
-// A oneLineInfo is a single PC and line number.
-type oneLineInfo struct {
- pc uint64
- line int
-}
-
-// A lineHdr holds the relevant information from a line number
-// program header.
-type lineHdr struct {
- version uint16 // version of line number encoding
- minInsnLen uint8 // minimum instruction length
- maxOpsPerInsn uint8 // maximum number of ops per instruction
- defStmt bool // initial value of stmt register
- lineBase int8 // line adjustment base
- lineRange uint8 // line adjustment step
- opBase uint8 // base of special opcode values
- opLen []uint8 // lengths of standard opcodes
- dirs []string // directories
- files []string // file names
-}
-
-// parseLine parses the line number information for a compilation unit
-func (d *Data) parseLine(u *unit) error {
- if u.lineoff+1 == 0 {
- return errors.New("unknown line offset")
- }
- b := makeBuf(d, u, "line", u.lineoff, d.line[u.lineoff:])
- len := uint64(b.uint32())
- dwarf64 := false
- if len == 0xffffffff {
- len = b.uint64()
- dwarf64 = true
- }
- end := b.off + Offset(len)
- hdr := d.parseLineHdr(u, &b, dwarf64)
- if b.err == nil {
- d.parseLineProgram(u, &b, hdr, end)
- }
- return b.err
-}
-
-// parseLineHdr parses a line number program header.
-func (d *Data) parseLineHdr(u *unit, b *buf, dwarf64 bool) (hdr lineHdr) {
- hdr.version = b.uint16()
- if hdr.version < 2 || hdr.version > 4 {
- b.error("unsupported DWARF version " + strconv.Itoa(int(hdr.version)))
- return
- }
-
- var hlen Offset
- if dwarf64 {
- hlen = Offset(b.uint64())
- } else {
- hlen = Offset(b.uint32())
- }
- end := b.off + hlen
-
- hdr.minInsnLen = b.uint8()
- if hdr.version < 4 {
- hdr.maxOpsPerInsn = 1
- } else {
- hdr.maxOpsPerInsn = b.uint8()
- }
-
- if b.uint8() == 0 {
- hdr.defStmt = false
- } else {
- hdr.defStmt = true
- }
- hdr.lineBase = int8(b.uint8())
- hdr.lineRange = b.uint8()
- hdr.opBase = b.uint8()
- hdr.opLen = b.bytes(int(hdr.opBase - 1))
-
- for d := b.string(); len(d) > 0; d = b.string() {
- hdr.dirs = append(hdr.dirs, d)
- }
-
- for f := b.string(); len(f) > 0; f = b.string() {
- d := b.uint()
- if !filepath.IsAbs(f) {
- if d > 0 {
- if d > uint64(len(hdr.dirs)) {
- b.error("DWARF directory index out of range")
- return
- }
- f = filepath.Join(hdr.dirs[d-1], f)
- } else if u.dir != "" {
- f = filepath.Join(u.dir, f)
- }
- }
- b.uint() // file's last mtime
- b.uint() // file length
- hdr.files = append(hdr.files, f)
- }
-
- if end > b.off {
- b.bytes(int(end - b.off))
- }
-
- return
-}
-
-// parseLineProgram parses a line program, adding information to
-// d.lineInfo as it goes.
-func (d *Data) parseLineProgram(u *unit, b *buf, hdr lineHdr, end Offset) {
- address := uint64(0)
- line := 1
- resetLineInfo := Line{
- Filename: "",
- OpIndex: 0,
- Line: 0,
- Column: 0,
- ISA: 0,
- Discriminator: 0,
- Stmt: hdr.defStmt,
- Block: false,
- EndPrologue: false,
- BeginEpilogue: false,
- }
- if len(hdr.files) > 0 {
- resetLineInfo.Filename = hdr.files[0]
- }
- lineInfo := resetLineInfo
-
- var lines []mapLineInfo
-
- minInsnLen := uint64(hdr.minInsnLen)
- maxOpsPerInsn := uint64(hdr.maxOpsPerInsn)
- lineBase := int(hdr.lineBase)
- lineRange := hdr.lineRange
- newLineInfo := true
- for b.off < end && b.err == nil {
- op := b.uint8()
- if op >= hdr.opBase {
- // This is a special opcode.
- op -= hdr.opBase
- advance := uint64(op / hdr.lineRange)
- opIndex := uint64(lineInfo.OpIndex)
- address += minInsnLen * ((opIndex + advance) / maxOpsPerInsn)
- newOpIndex := int((opIndex + advance) % maxOpsPerInsn)
- line += lineBase + int(op%lineRange)
- if newOpIndex != lineInfo.OpIndex {
- lineInfo.OpIndex = newOpIndex
- newLineInfo = true
- }
- lines, lineInfo, newLineInfo = d.addLine(lines, lineInfo, address, line, newLineInfo)
- } else if op == LineExtendedOp {
- c := b.uint()
- op = b.uint8()
- switch op {
- case LineExtEndSequence:
- u.lines = append(u.lines, lines...)
- lineInfo = resetLineInfo
- lines = nil
- newLineInfo = true
- case LineExtSetAddress:
- address = b.addr()
- case LineExtDefineFile:
- f := b.string()
- d := b.uint()
- b.uint() // mtime
- b.uint() // length
- if d > 0 && !filepath.IsAbs(f) {
- if d >= uint64(len(hdr.dirs)) {
- b.error("DWARF directory index out of range")
- return
- }
- f = filepath.Join(hdr.dirs[d-1], f)
- }
- hdr.files = append(hdr.files, f)
- case LineExtSetDiscriminator:
- lineInfo.Discriminator = int(b.uint())
- newLineInfo = true
- default:
- if c > 0 {
- b.bytes(int(c) - 1)
- }
- }
- } else {
- switch op {
- case LineCopy:
- lines, lineInfo, newLineInfo = d.addLine(lines, lineInfo, address, line, newLineInfo)
- case LineAdvancePC:
- advance := b.uint()
- opIndex := uint64(lineInfo.OpIndex)
- address += minInsnLen * ((opIndex + advance) / maxOpsPerInsn)
- newOpIndex := int((opIndex + advance) % maxOpsPerInsn)
- if newOpIndex != lineInfo.OpIndex {
- lineInfo.OpIndex = newOpIndex
- newLineInfo = true
- }
- case LineAdvanceLine:
- line += int(b.int())
- case LineSetFile:
- i := b.uint()
- if i > uint64(len(hdr.files)) {
- b.error("DWARF file number out of range")
- return
- }
- lineInfo.Filename = hdr.files[i-1]
- newLineInfo = true
- case LineSetColumn:
- lineInfo.Column = int(b.uint())
- newLineInfo = true
- case LineNegateStmt:
- lineInfo.Stmt = !lineInfo.Stmt
- newLineInfo = true
- case LineSetBasicBlock:
- lineInfo.Block = true
- newLineInfo = true
- case LineConstAddPC:
- op = 255 - hdr.opBase
- advance := uint64(op / hdr.lineRange)
- opIndex := uint64(lineInfo.OpIndex)
- address += minInsnLen * ((opIndex + advance) / maxOpsPerInsn)
- newOpIndex := int((opIndex + advance) % maxOpsPerInsn)
- if newOpIndex != lineInfo.OpIndex {
- lineInfo.OpIndex = newOpIndex
- newLineInfo = true
- }
- case LineFixedAdvancePC:
- address += uint64(b.uint16())
- if lineInfo.OpIndex != 0 {
- lineInfo.OpIndex = 0
- newLineInfo = true
- }
- case LineSetPrologueEnd:
- lineInfo.EndPrologue = true
- newLineInfo = true
- case LineSetEpilogueBegin:
- lineInfo.BeginEpilogue = true
- newLineInfo = true
- case LineSetISA:
- lineInfo.ISA = int(b.uint())
- newLineInfo = true
- default:
- if int(op) >= len(hdr.opLen) {
- b.error("DWARF line opcode has unknown length")
- return
- }
- for i := hdr.opLen[op-1]; i > 0; i-- {
- b.int()
- }
- }
- }
- }
-}
-
-// addLine adds the current address and line to lines using lineInfo.
-// If newLineInfo is true this is a new lineInfo. This returns the
-// updated lines, lineInfo, and newLineInfo.
-func (d *Data) addLine(lines []mapLineInfo, lineInfo Line, address uint64, line int, newLineInfo bool) ([]mapLineInfo, Line, bool) {
- if newLineInfo {
- if len(lines) > 0 {
- sort.Sort(lines[len(lines)-1].addrs)
- p := &lines[len(lines)-1]
- if len(p.addrs) > 0 && address > p.addrs[len(p.addrs)-1].pc {
- p.addrs = append(p.addrs, oneLineInfo{address, p.addrs[len(p.addrs)-1].line})
- }
- }
- lines = append(lines, mapLineInfo{line: lineInfo})
- }
- p := &lines[len(lines)-1]
- p.addrs = append(p.addrs, oneLineInfo{address, line})
-
- if lineInfo.Block || lineInfo.EndPrologue || lineInfo.BeginEpilogue || lineInfo.Discriminator != 0 {
- lineInfo.Block = false
- lineInfo.EndPrologue = false
- lineInfo.BeginEpilogue = false
- lineInfo.Discriminator = 0
- newLineInfo = true
- } else {
- newLineInfo = false
- }
-
- return lines, lineInfo, newLineInfo
-}