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