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