elf.go 2.0 KB

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