github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/pkg/dwarf/godwarf/sections.go (about)

     1  package godwarf
     2  
     3  import (
     4  	"bytes"
     5  	"compress/zlib"
     6  	"debug/elf"
     7  	"debug/macho"
     8  	"debug/pe"
     9  	"encoding/binary"
    10  	"fmt"
    11  	"io"
    12  )
    13  
    14  // GetDebugSectionElf returns the data contents of the specified debug
    15  // section, decompressing it if it is compressed.
    16  // For example GetDebugSectionElf("line") will return the contents of
    17  // .debug_line, if .debug_line doesn't exist it will try to return the
    18  // decompressed contents of .zdebug_line.
    19  func GetDebugSectionElf(f *elf.File, name string) ([]byte, error) {
    20  	sec := f.Section(".debug_" + name)
    21  	if sec != nil {
    22  		return sec.Data()
    23  	}
    24  	sec = f.Section(".zdebug_" + name)
    25  	if sec == nil {
    26  		return nil, fmt.Errorf("could not find .debug_%s section", name)
    27  	}
    28  	b, err := sec.Data()
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	return decompressMaybe(b)
    33  }
    34  
    35  // GetDebugSectionPE returns the data contents of the specified debug
    36  // section, decompressing it if it is compressed.
    37  // For example GetDebugSectionPE("line") will return the contents of
    38  // .debug_line, if .debug_line doesn't exist it will try to return the
    39  // decompressed contents of .zdebug_line.
    40  func GetDebugSectionPE(f *pe.File, name string) ([]byte, error) {
    41  	sec := f.Section(".debug_" + name)
    42  	if sec != nil {
    43  		return peSectionData(sec)
    44  	}
    45  	sec = f.Section(".zdebug_" + name)
    46  	if sec == nil {
    47  		return nil, fmt.Errorf("could not find .debug_%s section", name)
    48  	}
    49  	b, err := peSectionData(sec)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	return decompressMaybe(b)
    54  }
    55  
    56  func peSectionData(sec *pe.Section) ([]byte, error) {
    57  	b, err := sec.Data()
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  	if 0 < sec.VirtualSize && sec.VirtualSize < sec.Size {
    62  		b = b[:sec.VirtualSize]
    63  	}
    64  	return b, nil
    65  }
    66  
    67  // GetDebugSectionMacho returns the data contents of the specified debug
    68  // section, decompressing it if it is compressed.
    69  // For example GetDebugSectionMacho("line") will return the contents of
    70  // __debug_line, if __debug_line doesn't exist it will try to return the
    71  // decompressed contents of __zdebug_line.
    72  func GetDebugSectionMacho(f *macho.File, name string) ([]byte, error) {
    73  	sec := f.Section("__debug_" + name)
    74  	if sec != nil {
    75  		return sec.Data()
    76  	}
    77  	sec = f.Section("__zdebug_" + name)
    78  	if sec == nil {
    79  		return nil, fmt.Errorf("could not find .debug_%s section", name)
    80  	}
    81  	b, err := sec.Data()
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	return decompressMaybe(b)
    86  }
    87  
    88  func decompressMaybe(b []byte) ([]byte, error) {
    89  	if len(b) < 12 || string(b[:4]) != "ZLIB" {
    90  		// not compressed
    91  		return b, nil
    92  	}
    93  
    94  	dlen := binary.BigEndian.Uint64(b[4:12])
    95  	dbuf := make([]byte, dlen)
    96  	r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	if _, err := io.ReadFull(r, dbuf); err != nil {
   101  		return nil, err
   102  	}
   103  	if err := r.Close(); err != nil {
   104  		return nil, err
   105  	}
   106  	return dbuf, nil
   107  }