github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/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 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 }