github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/builder/elfpatch.go (about) 1 package builder 2 3 import ( 4 "debug/elf" 5 "fmt" 6 "os" 7 ) 8 9 func getElfSectionData(executable string, sectionName string) ([]byte, elf.FileHeader, error) { 10 elfFile, err := elf.Open(executable) 11 if err != nil { 12 return nil, elf.FileHeader{}, err 13 } 14 defer elfFile.Close() 15 16 section := elfFile.Section(sectionName) 17 if section == nil { 18 return nil, elf.FileHeader{}, fmt.Errorf("could not find %s section", sectionName) 19 } 20 21 data, err := section.Data() 22 23 return data, elfFile.FileHeader, err 24 } 25 26 func replaceElfSection(executable string, sectionName string, data []byte) error { 27 fp, err := os.OpenFile(executable, os.O_RDWR, 0) 28 if err != nil { 29 return err 30 } 31 defer fp.Close() 32 33 elfFile, err := elf.Open(executable) 34 if err != nil { 35 return err 36 } 37 defer elfFile.Close() 38 39 section := elfFile.Section(sectionName) 40 if section == nil { 41 return fmt.Errorf("could not find %s section", sectionName) 42 } 43 44 // Implicitly check for compressed sections 45 if section.Size != section.FileSize { 46 return fmt.Errorf("expected section %s to have identical size and file size, got %d and %d", sectionName, section.Size, section.FileSize) 47 } 48 49 // Only permit complete replacement of section 50 if section.Size != uint64(len(data)) { 51 return fmt.Errorf("expected section %s to have size %d, was actually %d", sectionName, len(data), section.Size) 52 } 53 54 // Write the replacement section data 55 _, err = fp.WriteAt(data, int64(section.Offset)) 56 return err 57 }