github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/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 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 nunit++ 52 } 53 if b.err != nil { 54 return nil, b.err 55 } 56 57 // Again, this time writing them down. 58 b = makeBuf(d, unknownFormat{}, "info", 0, d.info) 59 units := make([]unit, nunit) 60 for i := range units { 61 u := &units[i] 62 u.base = b.off 63 var n Offset 64 n, u.is64 = b.unitLength() 65 dataOff := b.off 66 vers := b.uint16() 67 if vers < 2 || vers > 5 { 68 b.error("unsupported DWARF version " + strconv.Itoa(int(vers))) 69 break 70 } 71 u.vers = int(vers) 72 if vers >= 5 { 73 u.utype = b.uint8() 74 u.asize = int(b.uint8()) 75 } 76 var abbrevOff uint64 77 if u.is64 { 78 abbrevOff = b.uint64() 79 } else { 80 abbrevOff = uint64(b.uint32()) 81 } 82 atable, err := d.parseAbbrev(abbrevOff, u.vers) 83 if err != nil { 84 if b.err == nil { 85 b.err = err 86 } 87 break 88 } 89 u.atable = atable 90 if vers < 5 { 91 u.asize = int(b.uint8()) 92 } 93 94 switch u.utype { 95 case utSkeleton, utSplitCompile: 96 b.uint64() // unit ID 97 case utType, utSplitType: 98 b.uint64() // type signature 99 if u.is64 { // type offset 100 b.uint64() 101 } else { 102 b.uint32() 103 } 104 } 105 106 u.off = b.off 107 u.data = b.bytes(int(n - (b.off - dataOff))) 108 } 109 if b.err != nil { 110 return nil, b.err 111 } 112 return units, nil 113 } 114 115 // offsetToUnit returns the index of the unit containing offset off. 116 // It returns -1 if no unit contains this offset. 117 func (d *Data) offsetToUnit(off Offset) int { 118 // Find the unit after off 119 next := sort.Search(len(d.unit), func(i int) bool { 120 return d.unit[i].off > off 121 }) 122 if next == 0 { 123 return -1 124 } 125 u := &d.unit[next-1] 126 if u.off <= off && off < u.off+Offset(len(u.data)) { 127 return next - 1 128 } 129 return -1 130 }