...

Source file src/debug/dwarf/unit.go

Documentation: debug/dwarf

		 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  		for n == 0 {
		67  			n, u.is64 = b.unitLength()
		68  		}
		69  		dataOff := b.off
		70  		vers := b.uint16()
		71  		if vers < 2 || vers > 5 {
		72  			b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
		73  			break
		74  		}
		75  		u.vers = int(vers)
		76  		if vers >= 5 {
		77  			u.utype = b.uint8()
		78  			u.asize = int(b.uint8())
		79  		}
		80  		var abbrevOff uint64
		81  		if u.is64 {
		82  			abbrevOff = b.uint64()
		83  		} else {
		84  			abbrevOff = uint64(b.uint32())
		85  		}
		86  		atable, err := d.parseAbbrev(abbrevOff, u.vers)
		87  		if err != nil {
		88  			if b.err == nil {
		89  				b.err = err
		90  			}
		91  			break
		92  		}
		93  		u.atable = atable
		94  		if vers < 5 {
		95  			u.asize = int(b.uint8())
		96  		}
		97  
		98  		switch u.utype {
		99  		case utSkeleton, utSplitCompile:
	 100  			b.uint64() // unit ID
	 101  		case utType, utSplitType:
	 102  			b.uint64()	// type signature
	 103  			if u.is64 { // type offset
	 104  				b.uint64()
	 105  			} else {
	 106  				b.uint32()
	 107  			}
	 108  		}
	 109  
	 110  		u.off = b.off
	 111  		u.data = b.bytes(int(n - (b.off - dataOff)))
	 112  	}
	 113  	if b.err != nil {
	 114  		return nil, b.err
	 115  	}
	 116  	return units, nil
	 117  }
	 118  
	 119  // offsetToUnit returns the index of the unit containing offset off.
	 120  // It returns -1 if no unit contains this offset.
	 121  func (d *Data) offsetToUnit(off Offset) int {
	 122  	// Find the unit after off
	 123  	next := sort.Search(len(d.unit), func(i int) bool {
	 124  		return d.unit[i].off > off
	 125  	})
	 126  	if next == 0 {
	 127  		return -1
	 128  	}
	 129  	u := &d.unit[next-1]
	 130  	if u.off <= off && off < u.off+Offset(len(u.data)) {
	 131  		return next - 1
	 132  	}
	 133  	return -1
	 134  }
	 135  

View as plain text