mirror of
https://github.com/beego/bee.git
synced 2024-12-23 16:40:50 +00:00
120 lines
3.7 KiB
Go
120 lines
3.7 KiB
Go
|
// Copyright 2014 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.
|
||
|
|
||
|
package dwarf
|
||
|
|
||
|
// This file provides simple methods to access the symbol table by name and address.
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"regexp"
|
||
|
"sort"
|
||
|
)
|
||
|
|
||
|
// lookupEntry returns the first Entry for the name.
|
||
|
// If tag is non-zero, only entries with that tag are considered.
|
||
|
func (d *Data) lookupEntry(name string, tag Tag) (*Entry, error) {
|
||
|
x, ok := d.nameCache[name]
|
||
|
if !ok {
|
||
|
return nil, fmt.Errorf("DWARF entry for %q not found", name)
|
||
|
}
|
||
|
for ; x != nil; x = x.link {
|
||
|
if tag == 0 || x.entry.Tag == tag {
|
||
|
return x.entry, nil
|
||
|
}
|
||
|
}
|
||
|
return nil, fmt.Errorf("no DWARF entry for %q with tag %s", name, tag)
|
||
|
}
|
||
|
|
||
|
// LookupMatchingSymbols returns the names of all top-level entries matching
|
||
|
// the given regular expression.
|
||
|
func (d *Data) LookupMatchingSymbols(nameRE *regexp.Regexp) (result []string, err error) {
|
||
|
for name := range d.nameCache {
|
||
|
if nameRE.MatchString(name) {
|
||
|
result = append(result, name)
|
||
|
}
|
||
|
}
|
||
|
return result, nil
|
||
|
}
|
||
|
|
||
|
// LookupEntry returns the Entry for the named symbol.
|
||
|
func (d *Data) LookupEntry(name string) (*Entry, error) {
|
||
|
return d.lookupEntry(name, 0)
|
||
|
}
|
||
|
|
||
|
// LookupFunction returns the entry for a function.
|
||
|
func (d *Data) LookupFunction(name string) (*Entry, error) {
|
||
|
return d.lookupEntry(name, TagSubprogram)
|
||
|
}
|
||
|
|
||
|
// LookupVariable returns the entry for a (global) variable.
|
||
|
func (d *Data) LookupVariable(name string) (*Entry, error) {
|
||
|
return d.lookupEntry(name, TagVariable)
|
||
|
}
|
||
|
|
||
|
// EntryLocation returns the address of the object referred to by the given Entry.
|
||
|
func (d *Data) EntryLocation(e *Entry) (uint64, error) {
|
||
|
loc, _ := e.Val(AttrLocation).([]byte)
|
||
|
if len(loc) == 0 {
|
||
|
return 0, fmt.Errorf("DWARF entry has no Location attribute")
|
||
|
}
|
||
|
// TODO: implement the DWARF Location bytecode. What we have here only
|
||
|
// recognizes a program with a single literal opAddr bytecode.
|
||
|
if asize := d.unit[0].asize; loc[0] == opAddr && len(loc) == 1+asize {
|
||
|
switch asize {
|
||
|
case 1:
|
||
|
return uint64(loc[1]), nil
|
||
|
case 2:
|
||
|
return uint64(d.order.Uint16(loc[1:])), nil
|
||
|
case 4:
|
||
|
return uint64(d.order.Uint32(loc[1:])), nil
|
||
|
case 8:
|
||
|
return d.order.Uint64(loc[1:]), nil
|
||
|
}
|
||
|
}
|
||
|
return 0, fmt.Errorf("DWARF entry has an unimplemented Location op")
|
||
|
}
|
||
|
|
||
|
// EntryType returns the Type for an Entry.
|
||
|
func (d *Data) EntryType(e *Entry) (Type, error) {
|
||
|
off, err := d.EntryTypeOffset(e)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return d.Type(off)
|
||
|
}
|
||
|
|
||
|
// EntryTypeOffset returns the offset in the given Entry's type attribute.
|
||
|
func (d *Data) EntryTypeOffset(e *Entry) (Offset, error) {
|
||
|
v := e.Val(AttrType)
|
||
|
if v == nil {
|
||
|
return 0, fmt.Errorf("DWARF entry has no Type attribute")
|
||
|
}
|
||
|
off, ok := v.(Offset)
|
||
|
if !ok {
|
||
|
return 0, fmt.Errorf("DWARF entry has an invalid Type attribute")
|
||
|
}
|
||
|
return off, nil
|
||
|
}
|
||
|
|
||
|
// PCToFunction returns the entry and address for the function containing the
|
||
|
// specified PC.
|
||
|
func (d *Data) PCToFunction(pc uint64) (entry *Entry, lowpc uint64, err error) {
|
||
|
p := d.pcToFuncEntries
|
||
|
if len(p) == 0 {
|
||
|
return nil, 0, fmt.Errorf("no function addresses loaded")
|
||
|
}
|
||
|
i := sort.Search(len(p), func(i int) bool { return p[i].pc > pc }) - 1
|
||
|
// The search failed if:
|
||
|
// - pc was before the start of any function.
|
||
|
// - The largest function bound not larger than pc was the end of a function,
|
||
|
// not the start of one.
|
||
|
// - The largest function bound not larger than pc was the start of a function
|
||
|
// that we don't know the end of, and the PC is much larger than the start.
|
||
|
if i == -1 || p[i].entry == nil || (i+1 == len(p) && pc-p[i].pc >= 1<<20) {
|
||
|
return nil, 0, fmt.Errorf("no function at %x", pc)
|
||
|
}
|
||
|
return p[i].entry, p[i].pc, nil
|
||
|
}
|