bee/vendor/github.com/derekparker/delve/pkg/dwarf/godwarf/sections.go

108 lines
2.7 KiB
Go

package godwarf
import (
"bytes"
"compress/zlib"
"debug/elf"
"debug/macho"
"debug/pe"
"encoding/binary"
"fmt"
"io"
)
// GetDebugSectionElf returns the data contents of the specified debug
// section, decompressing it if it is compressed.
// For example GetDebugSectionElf("line") will return the contents of
// .debug_line, if .debug_line doesn't exist it will try to return the
// decompressed contents of .zdebug_line.
func GetDebugSectionElf(f *elf.File, name string) ([]byte, error) {
sec := f.Section(".debug_" + name)
if sec != nil {
return sec.Data()
}
sec = f.Section(".zdebug_" + name)
if sec == nil {
return nil, fmt.Errorf("could not find .debug_%s section", name)
}
b, err := sec.Data()
if err != nil {
return nil, err
}
return decompressMaybe(b)
}
// GetDebugSectionPE returns the data contents of the specified debug
// section, decompressing it if it is compressed.
// For example GetDebugSectionPE("line") will return the contents of
// .debug_line, if .debug_line doesn't exist it will try to return the
// decompressed contents of .zdebug_line.
func GetDebugSectionPE(f *pe.File, name string) ([]byte, error) {
sec := f.Section(".debug_" + name)
if sec != nil {
return peSectionData(sec)
}
sec = f.Section(".zdebug_" + name)
if sec == nil {
return nil, fmt.Errorf("could not find .debug_%s section", name)
}
b, err := peSectionData(sec)
if err != nil {
return nil, err
}
return decompressMaybe(b)
}
func peSectionData(sec *pe.Section) ([]byte, error) {
b, err := sec.Data()
if err != nil {
return nil, err
}
if 0 < sec.VirtualSize && sec.VirtualSize < sec.Size {
b = b[:sec.VirtualSize]
}
return b, nil
}
// GetDebugSectionMacho returns the data contents of the specified debug
// section, decompressing it if it is compressed.
// For example GetDebugSectionMacho("line") will return the contents of
// __debug_line, if __debug_line doesn't exist it will try to return the
// decompressed contents of __zdebug_line.
func GetDebugSectionMacho(f *macho.File, name string) ([]byte, error) {
sec := f.Section("__debug_" + name)
if sec != nil {
return sec.Data()
}
sec = f.Section("__zdebug_" + name)
if sec == nil {
return nil, fmt.Errorf("could not find .debug_%s section", name)
}
b, err := sec.Data()
if err != nil {
return nil, err
}
return decompressMaybe(b)
}
func decompressMaybe(b []byte) ([]byte, error) {
if len(b) < 12 || string(b[:4]) != "ZLIB" {
// not compressed
return b, nil
}
dlen := binary.BigEndian.Uint64(b[4:12])
dbuf := make([]byte, dlen)
r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
if err != nil {
return nil, err
}
if _, err := io.ReadFull(r, dbuf); err != nil {
return nil, err
}
if err := r.Close(); err != nil {
return nil, err
}
return dbuf, nil
}