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 }