Home | History | Annotate | Download | only in dwarf
      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 		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
     69 		}
     70 		u.vers = int(vers)
     71 		var abbrevOff uint64
     72 		if u.is64 {
     73 			abbrevOff = b.uint64()
     74 		} else {
     75 			abbrevOff = uint64(b.uint32())
     76 		}
     77 		atable, err := d.parseAbbrev(abbrevOff, u.vers)
     78 		if err != nil {
     79 			if b.err == nil {
     80 				b.err = err
     81 			}
     82 			break
     83 		}
     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)))
     88 	}
     89 	if b.err != nil {
     90 		return nil, b.err
     91 	}
     92 	return units, nil
     93 }
     94 
     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
    101 	})
    102 	if next == 0 {
    103 		return -1
    104 	}
    105 	u := &d.unit[next-1]
    106 	if u.off <= off && off < u.off+Offset(len(u.data)) {
    107 		return next - 1
    108 	}
    109 	return -1
    110 }
    111