github.com/kubearmor/cilium@v1.6.12/pkg/alignchecker/elf.go (about) 1 // Copyright (c) 2009 The Go Authors. All rights reserved. 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google Inc. nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 package alignchecker 30 31 import ( 32 "bytes" 33 "compress/zlib" 34 "debug/dwarf" 35 "debug/elf" 36 "encoding/binary" 37 "fmt" 38 "io" 39 "strings" 40 ) 41 42 // Adopted from elf.File.DWARF 43 // https://github.com/golang/go/blob/master/src/debug/elf/file.go (go1.11.2). 44 // 45 // The former method function tries to apply relocations when extracting DWARF 46 // debug sections. Unfortunately, the relocations are not implemented for EM_BPF, 47 // so the method fails. 48 // 49 // For struct alignment checks, no relocations are needed, so we comment out 50 // the relocation bits. 51 // 52 // NOTE: DO NOT USE THE FUNCTION FOR ANYTHING ELSE! 53 func getDWARFFromELF(f *elf.File) (*dwarf.Data, error) { 54 dwarfSuffix := func(s *elf.Section) string { 55 switch { 56 case strings.HasPrefix(s.Name, ".debug_"): 57 return s.Name[7:] 58 case strings.HasPrefix(s.Name, ".zdebug_"): 59 return s.Name[8:] 60 default: 61 return "" 62 } 63 64 } 65 // sectionData gets the data for s, checks its size, and 66 // applies any applicable relations. 67 sectionData := func(i int, s *elf.Section) ([]byte, error) { 68 b, err := s.Data() 69 if err != nil && uint64(len(b)) < s.Size { 70 return nil, err 71 } 72 73 if len(b) >= 12 && string(b[:4]) == "ZLIB" { 74 dlen := binary.BigEndian.Uint64(b[4:12]) 75 dbuf := make([]byte, dlen) 76 r, err := zlib.NewReader(bytes.NewBuffer(b[12:])) 77 if err != nil { 78 return nil, err 79 } 80 if _, err := io.ReadFull(r, dbuf); err != nil { 81 return nil, err 82 } 83 if err := r.Close(); err != nil { 84 return nil, err 85 } 86 b = dbuf 87 } 88 89 for _, r := range f.Sections { 90 if r.Type != elf.SHT_RELA && r.Type != elf.SHT_REL { 91 continue 92 } 93 if int(r.Info) != i { 94 continue 95 } 96 //rd, err := r.Data() 97 _, err := r.Data() 98 if err != nil { 99 return nil, err 100 } 101 // err = f.applyRelocations(b, rd) 102 // if err != nil { 103 // return nil, err 104 // } 105 } 106 return b, nil 107 } 108 109 // There are many other DWARF sections, but these 110 // are the ones the debug/dwarf package uses. 111 // Don't bother loading others. 112 var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil, "ranges": nil} 113 for i, s := range f.Sections { 114 suffix := dwarfSuffix(s) 115 if suffix == "" { 116 continue 117 } 118 if _, ok := dat[suffix]; !ok { 119 continue 120 } 121 b, err := sectionData(i, s) 122 if err != nil { 123 return nil, err 124 } 125 dat[suffix] = b 126 } 127 128 d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, dat["ranges"], dat["str"]) 129 if err != nil { 130 return nil, err 131 } 132 133 // Look for DWARF4 .debug_types sections. 134 for i, s := range f.Sections { 135 suffix := dwarfSuffix(s) 136 if suffix != "types" { 137 continue 138 } 139 140 b, err := sectionData(i, s) 141 if err != nil { 142 return nil, err 143 } 144 145 err = d.AddTypes(fmt.Sprintf("types-%d", i), b) 146 if err != nil { 147 return nil, err 148 } 149 } 150 151 return d, nil 152 }