github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/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 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 }