elfpatch.go raw
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 }
58