section.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package loader
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "io"
  6. )
  7. // SectionTable manages reading/writing section entries
  8. type SectionTable struct {
  9. Entries []SectionEntry
  10. }
  11. // FindSection returns the first section of given type
  12. func (t *SectionTable) FindSection(stype SectionType) (*SectionEntry, error) {
  13. for i := range t.Entries {
  14. if t.Entries[i].Type == stype {
  15. return &t.Entries[i], nil
  16. }
  17. }
  18. return nil, fmt.Errorf("section type %d not found", stype)
  19. }
  20. // HasSection checks if a section type exists
  21. func (t *SectionTable) HasSection(stype SectionType) bool {
  22. for i := range t.Entries {
  23. if t.Entries[i].Type == stype {
  24. return true
  25. }
  26. }
  27. return false
  28. }
  29. // ReadSectionTable reads the section table from a reader
  30. func ReadSectionTable(r io.Reader, count uint32) (*SectionTable, error) {
  31. table := &SectionTable{
  32. Entries: make([]SectionEntry, count),
  33. }
  34. for i := uint32(0); i < count; i++ {
  35. var entry SectionEntry
  36. if err := binary.Read(r, binary.LittleEndian, &entry.Type); err != nil {
  37. return nil, fmt.Errorf("reading section type: %w", err)
  38. }
  39. if err := binary.Read(r, binary.LittleEndian, &entry.Offset); err != nil {
  40. return nil, fmt.Errorf("reading section offset: %w", err)
  41. }
  42. if err := binary.Read(r, binary.LittleEndian, &entry.Size); err != nil {
  43. return nil, fmt.Errorf("reading section size: %w", err)
  44. }
  45. if err := binary.Read(r, binary.LittleEndian, &entry.Flags); err != nil {
  46. return nil, fmt.Errorf("reading section flags: %w", err)
  47. }
  48. table.Entries[i] = entry
  49. }
  50. return table, nil
  51. }
  52. // WriteSectionTable writes the section table to a writer
  53. func WriteSectionTable(w io.Writer, table *SectionTable) error {
  54. for _, entry := range table.Entries {
  55. if err := binary.Write(w, binary.LittleEndian, entry.Type); err != nil {
  56. return err
  57. }
  58. if err := binary.Write(w, binary.LittleEndian, entry.Offset); err != nil {
  59. return err
  60. }
  61. if err := binary.Write(w, binary.LittleEndian, entry.Size); err != nil {
  62. return err
  63. }
  64. if err := binary.Write(w, binary.LittleEndian, entry.Flags); err != nil {
  65. return err
  66. }
  67. }
  68. return nil
  69. }
  70. // SectionEntrySize is the byte size of a single section entry
  71. const SectionEntrySize = 4 + 8 + 8 + 4 // Type + Offset + Size + Flags = 24 bytes