package dwarf
import (
"fmt"
"strconv"
)
type typeUnit struct {
unit
toff Offset
name string
cache Type
}
func (d *Data ) parseTypes (name string , types []byte ) error {
b := makeBuf (d , unknownFormat {}, name , 0 , types )
for len (b .data ) > 0 {
base := b .off
n , dwarf64 := b .unitLength ()
if n != Offset (uint32 (n )) {
b .error ("type unit length overflow" )
return b .err
}
hdroff := b .off
vers := int (b .uint16 ())
if vers != 4 {
b .error ("unsupported DWARF version " + strconv .Itoa (vers ))
return b .err
}
var ao uint64
if !dwarf64 {
ao = uint64 (b .uint32 ())
} else {
ao = b .uint64 ()
}
atable , err := d .parseAbbrev (ao , vers )
if err != nil {
return err
}
asize := b .uint8 ()
sig := b .uint64 ()
var toff uint32
if !dwarf64 {
toff = b .uint32 ()
} else {
to64 := b .uint64 ()
if to64 != uint64 (uint32 (to64 )) {
b .error ("type unit type offset overflow" )
return b .err
}
toff = uint32 (to64 )
}
boff := b .off
d .typeSigs [sig ] = &typeUnit {
unit : unit {
base : base ,
off : boff ,
data : b .bytes (int (n - (b .off - hdroff ))),
atable : atable ,
asize : int (asize ),
vers : vers ,
is64 : dwarf64 ,
},
toff : Offset (toff ),
name : name ,
}
if b .err != nil {
return b .err
}
}
return nil
}
func (d *Data ) sigToType (sig uint64 ) (Type , error ) {
tu := d .typeSigs [sig ]
if tu == nil {
return nil , fmt .Errorf ("no type unit with signature %v" , sig )
}
if tu .cache != nil {
return tu .cache , nil
}
b := makeBuf (d , tu , tu .name , tu .off , tu .data )
r := &typeUnitReader {d : d , tu : tu , b : b }
t , err := d .readType (tu .name , r , tu .toff , make (map [Offset ]Type ), nil )
if err != nil {
return nil , err
}
tu .cache = t
return t , nil
}
type typeUnitReader struct {
d *Data
tu *typeUnit
b buf
err error
}
func (tur *typeUnitReader ) Seek (off Offset ) {
tur .err = nil
doff := off - tur .tu .off
if doff < 0 || doff >= Offset (len (tur .tu .data )) {
tur .err = fmt .Errorf ("%s: offset %d out of range; max %d" , tur .tu .name , doff , len (tur .tu .data ))
return
}
tur .b = makeBuf (tur .d , tur .tu , tur .tu .name , off , tur .tu .data [doff :])
}
func (tur *typeUnitReader ) AddressSize () int {
return tur .tu .unit .asize
}
func (tur *typeUnitReader ) Next () (*Entry , error ) {
if tur .err != nil {
return nil , tur .err
}
if len (tur .tu .data ) == 0 {
return nil , nil
}
e := tur .b .entry (nil , tur .tu .atable , tur .tu .base , tur .tu .vers )
if tur .b .err != nil {
tur .err = tur .b .err
return nil , tur .err
}
return e , nil
}
func (tur *typeUnitReader ) clone () typeReader {
return &typeUnitReader {
d : tur .d ,
tu : tur .tu ,
b : makeBuf (tur .d , tur .tu , tur .tu .name , tur .tu .off , tur .tu .data ),
}
}
func (tur *typeUnitReader ) offset () Offset {
return tur .b .off
}
The pages are generated with Golds v0.7.0-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .