elf.go (2092B)
1 package internal 2 3 import ( 4 "debug/elf" 5 "fmt" 6 "io" 7 ) 8 9 type SafeELFFile struct { 10 *elf.File 11 } 12 13 // NewSafeELFFile reads an ELF safely. 14 // 15 // Any panic during parsing is turned into an error. This is necessary since 16 // there are a bunch of unfixed bugs in debug/elf. 17 // 18 // https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+debug%2Felf+in%3Atitle 19 func NewSafeELFFile(r io.ReaderAt) (safe *SafeELFFile, err error) { 20 defer func() { 21 r := recover() 22 if r == nil { 23 return 24 } 25 26 safe = nil 27 err = fmt.Errorf("reading ELF file panicked: %s", r) 28 }() 29 30 file, err := elf.NewFile(r) 31 if err != nil { 32 return nil, err 33 } 34 35 return &SafeELFFile{file}, nil 36 } 37 38 // OpenSafeELFFile reads an ELF from a file. 39 // 40 // It works like NewSafeELFFile, with the exception that safe.Close will 41 // close the underlying file. 42 func OpenSafeELFFile(path string) (safe *SafeELFFile, err error) { 43 defer func() { 44 r := recover() 45 if r == nil { 46 return 47 } 48 49 safe = nil 50 err = fmt.Errorf("reading ELF file panicked: %s", r) 51 }() 52 53 file, err := elf.Open(path) 54 if err != nil { 55 return nil, err 56 } 57 58 return &SafeELFFile{file}, nil 59 } 60 61 // Symbols is the safe version of elf.File.Symbols. 62 func (se *SafeELFFile) Symbols() (syms []elf.Symbol, err error) { 63 defer func() { 64 r := recover() 65 if r == nil { 66 return 67 } 68 69 syms = nil 70 err = fmt.Errorf("reading ELF symbols panicked: %s", r) 71 }() 72 73 syms, err = se.File.Symbols() 74 return 75 } 76 77 // DynamicSymbols is the safe version of elf.File.DynamicSymbols. 78 func (se *SafeELFFile) DynamicSymbols() (syms []elf.Symbol, err error) { 79 defer func() { 80 r := recover() 81 if r == nil { 82 return 83 } 84 85 syms = nil 86 err = fmt.Errorf("reading ELF dynamic symbols panicked: %s", r) 87 }() 88 89 syms, err = se.File.DynamicSymbols() 90 return 91 } 92 93 // SectionsByType returns all sections in the file with the specified section type. 94 func (se *SafeELFFile) SectionsByType(typ elf.SectionType) []*elf.Section { 95 sections := make([]*elf.Section, 0, 1) 96 for _, section := range se.Sections { 97 if section.Type == typ { 98 sections = append(sections, section) 99 } 100 } 101 return sections 102 }