github.com/kdevb0x/go@v0.0.0-20180115030120-39687051e9e7/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 dataOff := b.off 65 vers := b.uint16() 66 if vers != 2 && vers != 3 && vers != 4 { 67 b.error("unsupported DWARF version " + strconv.Itoa(int(vers))) 68 break 69 } 70 u.vers = int(vers) 71 var abbrevOff uint64 72 if u.is64 { 73 abbrevOff = b.uint64() 74 } else { 75 abbrevOff = uint64(b.uint32()) 76 } 77 atable, err := d.parseAbbrev(abbrevOff, u.vers) 78 if err != nil { 79 if b.err == nil { 80 b.err = err 81 } 82 break 83 } 84 u.atable = atable 85 u.asize = int(b.uint8()) 86 u.off = b.off 87 u.data = b.bytes(int(n - (b.off - dataOff))) 88 } 89 if b.err != nil { 90 return nil, b.err 91 } 92 return units, nil 93 } 94 95 // offsetToUnit returns the index of the unit containing offset off. 96 // It returns -1 if no unit contains this offset. 97 func (d *Data) offsetToUnit(off Offset) int { 98 // Find the unit after off 99 next := sort.Search(len(d.unit), func(i int) bool { 100 return d.unit[i].off > off 101 }) 102 if next == 0 { 103 return -1 104 } 105 u := &d.unit[next-1] 106 if u.off <= off && off < u.off+Offset(len(u.data)) { 107 return next - 1 108 } 109 return -1 110 }