github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/internal/elf.go (about)

     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  }