github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/dwarf/godwarf/tree.go (about)

     1  // The MIT License (MIT)
     2  
     3  // Copyright (c) 2014 Derek Parker
     4  
     5  // Permission is hereby granted, free of charge, to any person obtaining a copy of
     6  // this software and associated documentation files (the "Software"), to deal in
     7  // the Software without restriction, including without limitation the rights to
     8  // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
     9  // the Software, and to permit persons to whom the Software is furnished to do so,
    10  // subject to the following conditions:
    11  
    12  // The above copyright notice and this permission notice shall be included in all
    13  // copies or substantial portions of the Software.
    14  
    15  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
    17  // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
    18  // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    19  // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    20  // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    21  
    22  package godwarf
    23  
    24  import (
    25  	"debug/dwarf"
    26  	"fmt"
    27  	"sort"
    28  	"sync"
    29  )
    30  
    31  
    32  
    33  
    34  type Entry interface {
    35  	Val(dwarf.Attr) interface{}
    36  }
    37  
    38  type compositeEntry []*dwarf.Entry
    39  
    40  func (ce compositeEntry) Val(attr dwarf.Attr) interface{} {
    41  	for _, e := range ce {
    42  		if r := e.Val(attr); r != nil {
    43  			return r
    44  		}
    45  	}
    46  	return nil
    47  }
    48  
    49  
    50  
    51  
    52  func LoadAbstractOrigin(entry *dwarf.Entry, aordr *dwarf.Reader) (Entry, dwarf.Offset) {
    53  	ao, ok := entry.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)
    54  	if !ok {
    55  		return entry, entry.Offset
    56  	}
    57  
    58  	r := []*dwarf.Entry{entry}
    59  
    60  	for {
    61  		aordr.Seek(ao)
    62  		e, _ := aordr.Next()
    63  		if e == nil {
    64  			break
    65  		}
    66  		r = append(r, e)
    67  
    68  		ao, ok = e.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)
    69  		if !ok {
    70  			break
    71  		}
    72  	}
    73  
    74  	return compositeEntry(r), entry.Offset
    75  }
    76  
    77  
    78  type Tree struct {
    79  	Entry
    80  	typ      Type
    81  	Tag      dwarf.Tag
    82  	Offset   dwarf.Offset
    83  	Ranges   [][2]uint64
    84  	Children []*Tree
    85  }
    86  
    87  
    88  
    89  
    90  
    91  
    92  func LoadTree(off dwarf.Offset, dw *dwarf.Data, staticBase uint64) (*Tree, error) {
    93  	rdr := dw.Reader()
    94  	rdr.Seek(off)
    95  
    96  	e, err := rdr.Next()
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	r := entryToTreeInternal(e)
   101  	r.Children, err = loadTreeChildren(e, rdr)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	err = r.resolveRanges(dw, staticBase)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	r.resolveAbstractEntries(rdr)
   111  
   112  	return r, nil
   113  }
   114  
   115  
   116  func EntryToTree(entry *dwarf.Entry) *Tree {
   117  	if entry.Children {
   118  		panic(fmt.Sprintf("EntryToTree called on entry with children; "+
   119  			"LoadTree should have been used instead. entry: %+v", entry))
   120  	}
   121  	return entryToTreeInternal(entry)
   122  }
   123  
   124  func entryToTreeInternal(entry *dwarf.Entry) *Tree {
   125  	return &Tree{Entry: entry, Offset: entry.Offset, Tag: entry.Tag}
   126  }
   127  
   128  func loadTreeChildren(e *dwarf.Entry, rdr *dwarf.Reader) ([]*Tree, error) {
   129  	if !e.Children {
   130  		return nil, nil
   131  	}
   132  	children := []*Tree{}
   133  	for {
   134  		e, err := rdr.Next()
   135  		if err != nil {
   136  			return nil, err
   137  		}
   138  		if e.Tag == 0 {
   139  			break
   140  		}
   141  		child := entryToTreeInternal(e)
   142  		child.Children, err = loadTreeChildren(e, rdr)
   143  		if err != nil {
   144  			return nil, err
   145  		}
   146  		children = append(children, child)
   147  	}
   148  	return children, nil
   149  }
   150  
   151  func (n *Tree) resolveRanges(dw *dwarf.Data, staticBase uint64) error {
   152  	var err error
   153  	n.Ranges, err = dw.Ranges(n.Entry.(*dwarf.Entry))
   154  	if err != nil {
   155  		return err
   156  	}
   157  	for i := range n.Ranges {
   158  		n.Ranges[i][0] += staticBase
   159  		n.Ranges[i][1] += staticBase
   160  	}
   161  	n.Ranges = normalizeRanges(n.Ranges)
   162  
   163  	for _, child := range n.Children {
   164  		err := child.resolveRanges(dw, staticBase)
   165  		if err != nil {
   166  			return err
   167  		}
   168  		n.Ranges = fuseRanges(n.Ranges, child.Ranges)
   169  	}
   170  	return nil
   171  }
   172  
   173  
   174  func normalizeRanges(rngs [][2]uint64) [][2]uint64 {
   175  	const (
   176  		start = 0
   177  		end   = 1
   178  	)
   179  
   180  	if len(rngs) == 0 {
   181  		return rngs
   182  	}
   183  
   184  	sort.Slice(rngs, func(i, j int) bool {
   185  		return rngs[i][start] <= rngs[j][start]
   186  	})
   187  
   188  	
   189  	out := rngs[:0]
   190  	for i := range rngs {
   191  		if rngs[i][start] < rngs[i][end] {
   192  			out = append(out, rngs[i])
   193  		}
   194  	}
   195  	rngs = out
   196  
   197  	
   198  	out = rngs[:1]
   199  	for i := 1; i < len(rngs); i++ {
   200  		cur := rngs[i]
   201  		if cur[start] <= out[len(out)-1][end] {
   202  			out[len(out)-1][end] = max(cur[end], out[len(out)-1][end])
   203  		} else {
   204  			out = append(out, cur)
   205  		}
   206  	}
   207  	return out
   208  }
   209  
   210  func max(a, b uint64) uint64 {
   211  	if a > b {
   212  		return a
   213  	}
   214  	return b
   215  }
   216  
   217  
   218  
   219  
   220  
   221  
   222  func fuseRanges(rngs1, rngs2 [][2]uint64) [][2]uint64 {
   223  	if rangesContains(rngs1, rngs2) {
   224  		return rngs1
   225  	}
   226  
   227  	return normalizeRanges(append(rngs1, rngs2...))
   228  }
   229  
   230  
   231  func rangesContains(rngs1, rngs2 [][2]uint64) bool {
   232  	i, j := 0, 0
   233  	for {
   234  		if i >= len(rngs1) {
   235  			return false
   236  		}
   237  		if j >= len(rngs2) {
   238  			return true
   239  		}
   240  		if rangeContains(rngs1[i], rngs2[j]) {
   241  			j++
   242  		} else {
   243  			i++
   244  		}
   245  	}
   246  }
   247  
   248  
   249  func rangeContains(a, b [2]uint64) bool {
   250  	return a[0] <= b[0] && a[1] >= b[1]
   251  }
   252  
   253  func (n *Tree) resolveAbstractEntries(rdr *dwarf.Reader) {
   254  	n.Entry, n.Offset = LoadAbstractOrigin(n.Entry.(*dwarf.Entry), rdr)
   255  	for _, child := range n.Children {
   256  		child.resolveAbstractEntries(rdr)
   257  	}
   258  }
   259  
   260  
   261  func (n *Tree) ContainsPC(pc uint64) bool {
   262  	for _, rng := range n.Ranges {
   263  		if rng[0] > pc {
   264  			return false
   265  		}
   266  		if rng[0] <= pc && pc < rng[1] {
   267  			return true
   268  		}
   269  	}
   270  	return false
   271  }
   272  
   273  func (n *Tree) Type(dw *dwarf.Data, index int, typeCache *sync.Map) (Type, error) {
   274  	if n.typ == nil {
   275  		offset, ok := n.Val(dwarf.AttrType).(dwarf.Offset)
   276  		if !ok {
   277  			return nil, fmt.Errorf("malformed variable DIE (offset)")
   278  		}
   279  
   280  		var err error
   281  		n.typ, err = ReadType(dw, index, offset, typeCache)
   282  		if err != nil {
   283  			return nil, err
   284  		}
   285  	}
   286  	return n.typ, nil
   287  }