Source file src/debug/dwarf/unit.go

     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  	utype  uint8 // DWARF 5 unit type
    23  	is64   bool  // True for 64-bit DWARF format
    24  }
    25  
    26  // Implement the dataFormat interface.
    27  
    28  func (u *unit) version() int {
    29  	return u.vers
    30  }
    31  
    32  func (u *unit) dwarf64() (bool, bool) {
    33  	return u.is64, true
    34  }
    35  
    36  func (u *unit) addrsize() int {
    37  	return u.asize
    38  }
    39  
    40  func (d *Data) parseUnits() ([]unit, error) {
    41  	// Count units.
    42  	nunit := 0
    43  	b := makeBuf(d, unknownFormat{}, "info", 0, d.info)
    44  	for len(b.data) > 0 {
    45  		len, _ := b.unitLength()
    46  		if len != Offset(uint32(len)) {
    47  			b.error("unit length overflow")
    48  			break
    49  		}
    50  		b.skip(int(len))
    51  		if len > 0 {
    52  			nunit++
    53  		}
    54  	}
    55  	if b.err != nil {
    56  		return nil, b.err
    57  	}
    58  
    59  	// Again, this time writing them down.
    60  	b = makeBuf(d, unknownFormat{}, "info", 0, d.info)
    61  	units := make([]unit, nunit)
    62  	for i := range units {
    63  		u := &units[i]
    64  		u.base = b.off
    65  		var n Offset
    66  		if b.err != nil {
    67  			return nil, b.err
    68  		}
    69  		for n == 0 {
    70  			n, u.is64 = b.unitLength()
    71  		}
    72  		dataOff := b.off
    73  		vers := b.uint16()
    74  		if vers < 2 || vers > 5 {
    75  			b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
    76  			break
    77  		}
    78  		u.vers = int(vers)
    79  		if vers >= 5 {
    80  			u.utype = b.uint8()
    81  			u.asize = int(b.uint8())
    82  		}
    83  		var abbrevOff uint64
    84  		if u.is64 {
    85  			abbrevOff = b.uint64()
    86  		} else {
    87  			abbrevOff = uint64(b.uint32())
    88  		}
    89  		atable, err := d.parseAbbrev(abbrevOff, u.vers)
    90  		if err != nil {
    91  			if b.err == nil {
    92  				b.err = err
    93  			}
    94  			break
    95  		}
    96  		u.atable = atable
    97  		if vers < 5 {
    98  			u.asize = int(b.uint8())
    99  		}
   100  
   101  		switch u.utype {
   102  		case utSkeleton, utSplitCompile:
   103  			b.uint64() // unit ID
   104  		case utType, utSplitType:
   105  			b.uint64()  // type signature
   106  			if u.is64 { // type offset
   107  				b.uint64()
   108  			} else {
   109  				b.uint32()
   110  			}
   111  		}
   112  
   113  		u.off = b.off
   114  		u.data = b.bytes(int(n - (b.off - dataOff)))
   115  	}
   116  	if b.err != nil {
   117  		return nil, b.err
   118  	}
   119  	return units, nil
   120  }
   121  
   122  // offsetToUnit returns the index of the unit containing offset off.
   123  // It returns -1 if no unit contains this offset.
   124  func (d *Data) offsetToUnit(off Offset) int {
   125  	// Find the unit after off
   126  	next := sort.Search(len(d.unit), func(i int) bool {
   127  		return d.unit[i].off > off
   128  	})
   129  	if next == 0 {
   130  		return -1
   131  	}
   132  	u := &d.unit[next-1]
   133  	if u.off <= off && off < u.off+Offset(len(u.data)) {
   134  		return next - 1
   135  	}
   136  	return -1
   137  }
   138  

View as plain text