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