Source file src/pkg/debug/dwarf/entry.go
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 // DWARF debug information entry parser. 6 // An entry is a sequence of data items of a given format. 7 // The first word in the entry is an index into what DWARF 8 // calls the ``abbreviation table.'' An abbreviation is really 9 // just a type descriptor: it's an array of attribute tag/value format pairs. 10 11 package dwarf 12 13 import "errors" 14 15 // a single entry's description: a sequence of attributes 16 type abbrev struct { 17 tag Tag 18 children bool 19 field []afield 20 } 21 22 type afield struct { 23 attr Attr 24 fmt format 25 } 26 27 // a map from entry format ids to their descriptions 28 type abbrevTable map[uint32]abbrev 29 30 // ParseAbbrev returns the abbreviation table that starts at byte off 31 // in the .debug_abbrev section. 32 func (d *Data) parseAbbrev(off uint32) (abbrevTable, error) { 33 if m, ok := d.abbrevCache[off]; ok { 34 return m, nil 35 } 36 37 data := d.abbrev 38 if off > uint32(len(data)) { 39 data = nil 40 } else { 41 data = data[off:] 42 } 43 b := makeBuf(d, "abbrev", 0, data, 0) 44 45 // Error handling is simplified by the buf getters 46 // returning an endless stream of 0s after an error. 47 m := make(abbrevTable) 48 for { 49 // Table ends with id == 0. 50 id := uint32(b.uint()) 51 if id == 0 { 52 break 53 } 54 55 // Walk over attributes, counting. 56 n := 0 57 b1 := b // Read from copy of b. 58 b1.uint() 59 b1.uint8() 60 for { 61 tag := b1.uint() 62 fmt := b1.uint() 63 if tag == 0 && fmt == 0 { 64 break 65 } 66 n++ 67 } 68 if b1.err != nil { 69 return nil, b1.err 70 } 71 72 // Walk over attributes again, this time writing them down. 73 var a abbrev 74 a.tag = Tag(b.uint()) 75 a.children = b.uint8() != 0 76 a.field = make([]afield, n) 77 for i := range a.field { 78 a.field[i].attr = Attr(b.uint()) 79 a.field[i].fmt = format(b.uint()) 80 } 81 b.uint() 82 b.uint() 83 84 m[id] = a 85 } 86 if b.err != nil { 87 return nil, b.err 88 } 89 d.abbrevCache[off] = m 90 return m, nil 91 } 92 93 // An entry is a sequence of attribute/value pairs. 94 type Entry struct { 95 Offset Offset // offset of Entry in DWARF info 96 Tag Tag // tag (kind of Entry) 97 Children bool // whether Entry is followed by children 98 Field []Field 99 } 100 101 // A Field is a single attribute/value pair in an Entry. 102 type Field struct { 103 Attr Attr 104 Val interface{} 105 } 106 107 // Val returns the value associated with attribute Attr in Entry, 108 // or nil if there is no such attribute. 109 // 110 // A common idiom is to merge the check for nil return with 111 // the check that the value has the expected dynamic type, as in: 112 // v, ok := e.Val(AttrSibling).(int64); 113 // 114 func (e *Entry) Val(a Attr) interface{} { 115 for _, f := range e.Field { 116 if f.Attr == a { 117 return f.Val 118 } 119 } 120 return nil 121 } 122 123 // An Offset represents the location of an Entry within the DWARF info. 124 // (See Reader.Seek.) 125 type Offset uint32 126 127 // Entry reads a single entry from buf, decoding 128 // according to the given abbreviation table. 129 func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { 130 off := b.off 131 id := uint32(b.uint()) 132 if id == 0 { 133 return &Entry{} 134 } 135 a, ok := atab[id] 136 if !ok { 137 b.error("unknown abbreviation table index") 138 return nil 139 } 140 e := &Entry{ 141 Offset: off, 142 Tag: a.tag, 143 Children: a.children, 144 Field: make([]Field, len(a.field)), 145 } 146 for i := range e.Field { 147 e.Field[i].Attr = a.field[i].attr 148 fmt := a.field[i].fmt 149 if fmt == formIndirect { 150 fmt = format(b.uint()) 151 } 152 var val interface{} 153 switch fmt { 154 default: 155 b.error("unknown entry attr format") 156 157 // address 158 case formAddr: 159 val = b.addr() 160 161 // block 162 case formDwarfBlock1: 163 val = b.bytes(int(b.uint8())) 164 case formDwarfBlock2: 165 val = b.bytes(int(b.uint16())) 166 case formDwarfBlock4: 167 val = b.bytes(int(b.uint32())) 168 case formDwarfBlock: 169 val = b.bytes(int(b.uint())) 170 171 // constant 172 case formData1: 173 val = int64(b.uint8()) 174 case formData2: 175 val = int64(b.uint16()) 176 case formData4: 177 val = int64(b.uint32()) 178 case formData8: 179 val = int64(b.uint64()) 180 case formSdata: 181 val = int64(b.int()) 182 case formUdata: 183 val = int64(b.uint()) 184 185 // flag 186 case formFlag: 187 val = b.uint8() == 1 188 189 // reference to other entry 190 case formRefAddr: 191 val = Offset(b.addr()) 192 case formRef1: 193 val = Offset(b.uint8()) + ubase 194 case formRef2: 195 val = Offset(b.uint16()) + ubase 196 case formRef4: 197 val = Offset(b.uint32()) + ubase 198 case formRef8: 199 val = Offset(b.uint64()) + ubase 200 case formRefUdata: 201 val = Offset(b.uint()) + ubase 202 203 // string 204 case formString: 205 val = b.string() 206 case formStrp: 207 off := b.uint32() // offset into .debug_str 208 if b.err != nil { 209 return nil 210 } 211 b1 := makeBuf(b.dwarf, "str", 0, b.dwarf.str, 0) 212 b1.skip(int(off)) 213 val = b1.string() 214 if b1.err != nil { 215 b.err = b1.err 216 return nil 217 } 218 } 219 e.Field[i].Val = val 220 } 221 if b.err != nil { 222 return nil 223 } 224 return e 225 } 226 227 // A Reader allows reading Entry structures from a DWARF ``info'' section. 228 // The Entry structures are arranged in a tree. The Reader's Next function 229 // return successive entries from a pre-order traversal of the tree. 230 // If an entry has children, its Children field will be true, and the children 231 // follow, terminated by an Entry with Tag 0. 232 type Reader struct { 233 b buf 234 d *Data 235 err error 236 unit int 237 lastChildren bool // .Children of last entry returned by Next 238 lastSibling Offset // .Val(AttrSibling) of last entry returned by Next 239 } 240 241 // Reader returns a new Reader for Data. 242 // The reader is positioned at byte offset 0 in the DWARF ``info'' section. 243 func (d *Data) Reader() *Reader { 244 r := &Reader{d: d} 245 r.Seek(0) 246 return r 247 } 248 249 // Seek positions the Reader at offset off in the encoded entry stream. 250 // Offset 0 can be used to denote the first entry. 251 func (r *Reader) Seek(off Offset) { 252 d := r.d 253 r.err = nil 254 r.lastChildren = false 255 if off == 0 { 256 if len(d.unit) == 0 { 257 return 258 } 259 u := &d.unit[0] 260 r.unit = 0 261 r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize) 262 return 263 } 264 265 // TODO(rsc): binary search (maybe a new package) 266 var i int 267 var u *unit 268 for i = range d.unit { 269 u = &d.unit[i] 270 if u.off <= off && off < u.off+Offset(len(u.data)) { 271 r.unit = i 272 r.b = makeBuf(r.d, "info", off, u.data[off-u.off:], u.addrsize) 273 return 274 } 275 } 276 r.err = errors.New("offset out of range") 277 } 278 279 // maybeNextUnit advances to the next unit if this one is finished. 280 func (r *Reader) maybeNextUnit() { 281 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { 282 r.unit++ 283 u := &r.d.unit[r.unit] 284 r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize) 285 } 286 } 287 288 // Next reads the next entry from the encoded entry stream. 289 // It returns nil, nil when it reaches the end of the section. 290 // It returns an error if the current offset is invalid or the data at the 291 // offset cannot be decoded as a valid Entry. 292 func (r *Reader) Next() (*Entry, error) { 293 if r.err != nil { 294 return nil, r.err 295 } 296 r.maybeNextUnit() 297 if len(r.b.data) == 0 { 298 return nil, nil 299 } 300 u := &r.d.unit[r.unit] 301 e := r.b.entry(u.atable, u.base) 302 if r.b.err != nil { 303 r.err = r.b.err 304 return nil, r.err 305 } 306 if e != nil { 307 r.lastChildren = e.Children 308 if r.lastChildren { 309 r.lastSibling, _ = e.Val(AttrSibling).(Offset) 310 } 311 } else { 312 r.lastChildren = false 313 } 314 return e, nil 315 } 316 317 // SkipChildren skips over the child entries associated with 318 // the last Entry returned by Next. If that Entry did not have 319 // children or Next has not been called, SkipChildren is a no-op. 320 func (r *Reader) SkipChildren() { 321 if r.err != nil || !r.lastChildren { 322 return 323 } 324 325 // If the last entry had a sibling attribute, 326 // that attribute gives the offset of the next 327 // sibling, so we can avoid decoding the 328 // child subtrees. 329 if r.lastSibling >= r.b.off { 330 r.Seek(r.lastSibling) 331 return 332 } 333 334 for { 335 e, err := r.Next() 336 if err != nil || e == nil || e.Tag == 0 { 337 break 338 } 339 if e.Children { 340 r.SkipChildren() 341 } 342 } 343 }