LWG 3035. std::allocator's constructors should be constexpr
[official-gcc.git] / libgo / go / debug / dwarf / unit.go
blob98024ca1f8459fb1481a7a001528c3d09b65498a
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.
5 package dwarf
7 import (
8 "sort"
9 "strconv"
12 // DWARF debug info is split into a sequence of compilation units.
13 // Each unit has its own abbreviation table and address size.
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
25 // Implement the dataFormat interface.
27 func (u *unit) version() int {
28 return u.vers
31 func (u *unit) dwarf64() (bool, bool) {
32 return u.is64, true
35 func (u *unit) addrsize() int {
36 return u.asize
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
49 b.skip(int(len))
50 nunit++
52 if b.err != nil {
53 return nil, b.err
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
70 u.vers = int(vers)
71 var abbrevOff uint64
72 if u.is64 {
73 abbrevOff = b.uint64()
74 } else {
75 abbrevOff = uint64(b.uint32())
77 atable, err := d.parseAbbrev(abbrevOff, u.vers)
78 if err != nil {
79 if b.err == nil {
80 b.err = err
82 break
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)))
89 if b.err != nil {
90 return nil, b.err
92 return units, nil
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
102 if next == 0 {
103 return -1
105 u := &d.unit[next-1]
106 if u.off <= off && off < u.off+Offset(len(u.data)) {
107 return next - 1
109 return -1