github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/debug/dwarf/unit.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package dwarf
     6  
     7  import (
     8  	"sort"
     9  	"strconv"
    10  )
    11  
    12  // DWARF debug info is split into a sequence of compilation units.
    13  // Each unit has its own abbreviation table and address size.
    14  
    15  type unit struct {
    16  	base   Offset // byte offset of header within the aggregate info
    17  	off    Offset // byte offset of data within the aggregate info
    18  	data   []byte
    19  	atable abbrevTable
    20  	asize  int
    21  	vers   int
    22  	is64   bool // True for 64-bit DWARF format
    23  }
    24  
    25  // Implement the dataFormat interface.
    26  
    27  func (u *unit) version() int {
    28  	return u.vers
    29  }
    30  
    31  func (u *unit) dwarf64() (bool, bool) {
    32  	return u.is64, true
    33  }
    34  
    35  func (u *unit) addrsize() int {
    36  	return u.asize
    37  }
    38  
    39  func (d *Data) parseUnits() ([]unit, error) {
    40  	// Count units.
    41  	nunit := 0
    42  	b := makeBuf(d, unknownFormat{}, "info", 0, d.info)
    43  	for len(b.data) > 0 {
    44  		len, _ := b.unitLength()
    45  		if len != Offset(uint32(len)) {
    46  			b.error("unit length overflow")
    47  			break
    48  		}
    49  		b.skip(int(len))
    50  		nunit++
    51  	}
    52  	if b.err != nil {
    53  		return nil, b.err
    54  	}
    55  
    56  	// Again, this time writing them down.
    57  	b = makeBuf(d, unknownFormat{}, "info", 0, d.info)
    58  	units := make([]unit, nunit)
    59  	for i := range units {
    60  		u := &units[i]
    61  		u.base = b.off
    62  		var n Offset
    63  		n, u.is64 = b.unitLength()
    64  		vers := b.uint16()
    65  		if vers != 2 && vers != 3 && vers != 4 {
    66  			b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
    67  			break
    68  		}
    69  		u.vers = int(vers)
    70  		atable, err := d.parseAbbrev(b.uint32(), u.vers)
    71  		if err != nil {
    72  			if b.err == nil {
    73  				b.err = err
    74  			}
    75  			break
    76  		}
    77  		u.atable = atable
    78  		u.asize = int(b.uint8())
    79  		u.off = b.off
    80  		u.data = b.bytes(int(n - (2 + 4 + 1)))
    81  	}
    82  	if b.err != nil {
    83  		return nil, b.err
    84  	}
    85  	return units, nil
    86  }
    87  
    88  // offsetToUnit returns the index of the unit containing offset off.
    89  // It returns -1 if no unit contains this offset.
    90  func (d *Data) offsetToUnit(off Offset) int {
    91  	// Find the unit after off
    92  	next := sort.Search(len(d.unit), func(i int) bool {
    93  		return d.unit[i].off > off
    94  	})
    95  	if next == 0 {
    96  		return -1
    97  	}
    98  	u := &d.unit[next-1]
    99  	if u.off <= off && off < u.off+Offset(len(u.data)) {
   100  		return next - 1
   101  	}
   102  	return -1
   103  }