diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/pkg/debug/dwarf/entry.go | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/pkg/debug/dwarf/entry.go')
-rw-r--r-- | src/pkg/debug/dwarf/entry.go | 401 |
1 files changed, 0 insertions, 401 deletions
diff --git a/src/pkg/debug/dwarf/entry.go b/src/pkg/debug/dwarf/entry.go deleted file mode 100644 index 665c6840d..000000000 --- a/src/pkg/debug/dwarf/entry.go +++ /dev/null @@ -1,401 +0,0 @@ -// 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. - -// DWARF debug information entry parser. -// An entry is a sequence of data items of a given format. -// The first word in the entry is an index into what DWARF -// calls the ``abbreviation table.'' An abbreviation is really -// just a type descriptor: it's an array of attribute tag/value format pairs. - -package dwarf - -import ( - "errors" - "strconv" -) - -// a single entry's description: a sequence of attributes -type abbrev struct { - tag Tag - children bool - field []afield -} - -type afield struct { - attr Attr - fmt format -} - -// a map from entry format ids to their descriptions -type abbrevTable map[uint32]abbrev - -// ParseAbbrev returns the abbreviation table that starts at byte off -// in the .debug_abbrev section. -func (d *Data) parseAbbrev(off uint32) (abbrevTable, error) { - if m, ok := d.abbrevCache[off]; ok { - return m, nil - } - - data := d.abbrev - if off > uint32(len(data)) { - data = nil - } else { - data = data[off:] - } - b := makeBuf(d, unknownFormat{}, "abbrev", 0, data) - - // Error handling is simplified by the buf getters - // returning an endless stream of 0s after an error. - m := make(abbrevTable) - for { - // Table ends with id == 0. - id := uint32(b.uint()) - if id == 0 { - break - } - - // Walk over attributes, counting. - n := 0 - b1 := b // Read from copy of b. - b1.uint() - b1.uint8() - for { - tag := b1.uint() - fmt := b1.uint() - if tag == 0 && fmt == 0 { - break - } - n++ - } - if b1.err != nil { - return nil, b1.err - } - - // Walk over attributes again, this time writing them down. - var a abbrev - a.tag = Tag(b.uint()) - a.children = b.uint8() != 0 - a.field = make([]afield, n) - for i := range a.field { - a.field[i].attr = Attr(b.uint()) - a.field[i].fmt = format(b.uint()) - } - b.uint() - b.uint() - - m[id] = a - } - if b.err != nil { - return nil, b.err - } - d.abbrevCache[off] = m - return m, nil -} - -// An entry is a sequence of attribute/value pairs. -type Entry struct { - Offset Offset // offset of Entry in DWARF info - Tag Tag // tag (kind of Entry) - Children bool // whether Entry is followed by children - Field []Field -} - -// A Field is a single attribute/value pair in an Entry. -type Field struct { - Attr Attr - Val interface{} -} - -// Val returns the value associated with attribute Attr in Entry, -// or nil if there is no such attribute. -// -// A common idiom is to merge the check for nil return with -// the check that the value has the expected dynamic type, as in: -// v, ok := e.Val(AttrSibling).(int64); -// -func (e *Entry) Val(a Attr) interface{} { - for _, f := range e.Field { - if f.Attr == a { - return f.Val - } - } - return nil -} - -// An Offset represents the location of an Entry within the DWARF info. -// (See Reader.Seek.) -type Offset uint32 - -// Entry reads a single entry from buf, decoding -// according to the given abbreviation table. -func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { - off := b.off - id := uint32(b.uint()) - if id == 0 { - return &Entry{} - } - a, ok := atab[id] - if !ok { - b.error("unknown abbreviation table index") - return nil - } - e := &Entry{ - Offset: off, - Tag: a.tag, - Children: a.children, - Field: make([]Field, len(a.field)), - } - for i := range e.Field { - e.Field[i].Attr = a.field[i].attr - fmt := a.field[i].fmt - if fmt == formIndirect { - fmt = format(b.uint()) - } - var val interface{} - switch fmt { - default: - b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16)) - - // address - case formAddr: - val = b.addr() - - // block - case formDwarfBlock1: - val = b.bytes(int(b.uint8())) - case formDwarfBlock2: - val = b.bytes(int(b.uint16())) - case formDwarfBlock4: - val = b.bytes(int(b.uint32())) - case formDwarfBlock: - val = b.bytes(int(b.uint())) - - // constant - case formData1: - val = int64(b.uint8()) - case formData2: - val = int64(b.uint16()) - case formData4: - val = int64(b.uint32()) - case formData8: - val = int64(b.uint64()) - case formSdata: - val = int64(b.int()) - case formUdata: - val = int64(b.uint()) - - // flag - case formFlag: - val = b.uint8() == 1 - // New in DWARF 4. - case formFlagPresent: - // The attribute is implicitly indicated as present, and no value is - // encoded in the debugging information entry itself. - val = true - - // reference to other entry - case formRefAddr: - vers := b.format.version() - if vers == 0 { - b.error("unknown version for DW_FORM_ref_addr") - } else if vers == 2 { - val = Offset(b.addr()) - } else { - is64, known := b.format.dwarf64() - if !known { - b.error("unknown size for DW_FORM_ref_addr") - } else if is64 { - val = Offset(b.uint64()) - } else { - val = Offset(b.uint32()) - } - } - case formRef1: - val = Offset(b.uint8()) + ubase - case formRef2: - val = Offset(b.uint16()) + ubase - case formRef4: - val = Offset(b.uint32()) + ubase - case formRef8: - val = Offset(b.uint64()) + ubase - case formRefUdata: - val = Offset(b.uint()) + ubase - - // string - case formString: - val = b.string() - case formStrp: - off := b.uint32() // offset into .debug_str - if b.err != nil { - return nil - } - b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str) - b1.skip(int(off)) - val = b1.string() - if b1.err != nil { - b.err = b1.err - return nil - } - - // lineptr, loclistptr, macptr, rangelistptr - // New in DWARF 4, but clang can generate them with -gdwarf-2. - // Section reference, replacing use of formData4 and formData8. - case formSecOffset, formGnuRefAlt, formGnuStrpAlt: - is64, known := b.format.dwarf64() - if !known { - b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16)) - } else if is64 { - val = int64(b.uint64()) - } else { - val = int64(b.uint32()) - } - - // exprloc - // New in DWARF 4. - case formExprloc: - val = b.bytes(int(b.uint())) - - // reference - // New in DWARF 4. - case formRefSig8: - // 64-bit type signature. - val = b.uint64() - } - e.Field[i].Val = val - } - if b.err != nil { - return nil - } - return e -} - -// A Reader allows reading Entry structures from a DWARF ``info'' section. -// The Entry structures are arranged in a tree. The Reader's Next function -// return successive entries from a pre-order traversal of the tree. -// If an entry has children, its Children field will be true, and the children -// follow, terminated by an Entry with Tag 0. -type Reader struct { - b buf - d *Data - err error - unit int - lastChildren bool // .Children of last entry returned by Next - lastSibling Offset // .Val(AttrSibling) of last entry returned by Next -} - -// Reader returns a new Reader for Data. -// The reader is positioned at byte offset 0 in the DWARF ``info'' section. -func (d *Data) Reader() *Reader { - r := &Reader{d: d} - r.Seek(0) - return r -} - -// Seek positions the Reader at offset off in the encoded entry stream. -// Offset 0 can be used to denote the first entry. -func (r *Reader) Seek(off Offset) { - d := r.d - r.err = nil - r.lastChildren = false - if off == 0 { - if len(d.unit) == 0 { - return - } - u := &d.unit[0] - r.unit = 0 - r.b = makeBuf(r.d, u, "info", u.off, u.data) - return - } - - // TODO(rsc): binary search (maybe a new package) - var i int - var u *unit - for i = range d.unit { - u = &d.unit[i] - if u.off <= off && off < u.off+Offset(len(u.data)) { - r.unit = i - r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:]) - return - } - } - r.err = errors.New("offset out of range") -} - -// maybeNextUnit advances to the next unit if this one is finished. -func (r *Reader) maybeNextUnit() { - for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { - r.unit++ - u := &r.d.unit[r.unit] - r.b = makeBuf(r.d, u, "info", u.off, u.data) - } -} - -// Next reads the next entry from the encoded entry stream. -// It returns nil, nil when it reaches the end of the section. -// It returns an error if the current offset is invalid or the data at the -// offset cannot be decoded as a valid Entry. -func (r *Reader) Next() (*Entry, error) { - if r.err != nil { - return nil, r.err - } - r.maybeNextUnit() - if len(r.b.data) == 0 { - return nil, nil - } - u := &r.d.unit[r.unit] - e := r.b.entry(u.atable, u.base) - if r.b.err != nil { - r.err = r.b.err - return nil, r.err - } - if e != nil { - r.lastChildren = e.Children - if r.lastChildren { - r.lastSibling, _ = e.Val(AttrSibling).(Offset) - } - } else { - r.lastChildren = false - } - return e, nil -} - -// SkipChildren skips over the child entries associated with -// the last Entry returned by Next. If that Entry did not have -// children or Next has not been called, SkipChildren is a no-op. -func (r *Reader) SkipChildren() { - if r.err != nil || !r.lastChildren { - return - } - - // If the last entry had a sibling attribute, - // that attribute gives the offset of the next - // sibling, so we can avoid decoding the - // child subtrees. - if r.lastSibling >= r.b.off { - r.Seek(r.lastSibling) - return - } - - for { - e, err := r.Next() - if err != nil || e == nil || e.Tag == 0 { - break - } - if e.Children { - r.SkipChildren() - } - } -} - -// clone returns a copy of the reader. This is used by the typeReader -// interface. -func (r *Reader) clone() typeReader { - return r.d.Reader() -} - -// offset returns the current buffer offset. This is used by the -// typeReader interface. -func (r *Reader) offset() Offset { - return r.b.off -} |