diff options
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.go | 481 |
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 -} |