...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package time
17
18 import (
19 "bytes"
20 "debug/elf"
21 "embed"
22 "encoding/binary"
23
24 "github.com/pkg/errors"
25 )
26
27
28 var fakeclock embed.FS
29
30 const textSection = ".text"
31 const relocationSection = ".rela.text"
32
33
34 func LoadFakeImageFromEmbedFs(filename string, symbolName string) (*FakeImage, error) {
35 path := "fakeclock/" + filename
36 object, err := fakeclock.ReadFile(path)
37 if err != nil {
38 return nil, errors.Wrapf(err, "read file from embedded fs %s", path)
39 }
40
41 elfFile, err := elf.NewFile(bytes.NewReader(object))
42 if err != nil {
43 return nil, errors.Wrapf(err, "parse elf file %s", path)
44 }
45
46 syms, err := elfFile.Symbols()
47 if err != nil {
48 return nil, errors.Wrapf(err, "get symbols %s", path)
49 }
50
51 fakeImage := FakeImage{
52 symbolName: symbolName,
53 offset: make(map[string]int),
54 }
55 for _, r := range elfFile.Sections {
56
57 if r.Type == elf.SHT_PROGBITS && r.Name == textSection {
58 fakeImage.content, err = r.Data()
59 if err != nil {
60 return nil, errors.Wrapf(err, "read text section data %s", path)
61 }
62 break
63 }
64 }
65
66 for _, r := range elfFile.Sections {
67 if r.Type == elf.SHT_RELA && r.Name == relocationSection {
68 rela_section, err := r.Data()
69 if err != nil {
70 return nil, errors.Wrapf(err, "read rela section data %s", path)
71 }
72 rela_section_reader := bytes.NewReader(rela_section)
73
74 var rela elf.Rela64
75 for rela_section_reader.Len() > 0 {
76 err := binary.Read(rela_section_reader, elfFile.ByteOrder, &rela)
77 if err != nil {
78 return nil, errors.Wrapf(err, "read rela section rela64 entry %s", path)
79 }
80
81 symNo := rela.Info >> 32
82 if symNo == 0 || symNo > uint64(len(syms)) {
83 continue
84 }
85
86
87
88
89
90
91
92
93
94
95
96
97 sym := &syms[symNo-1]
98 fakeImage.offset[sym.Name] = len(fakeImage.content)
99 targetOffset := uint32(len(fakeImage.content)) - uint32(rela.Off) + uint32(rela.Addend)
100 elfFile.ByteOrder.PutUint32(fakeImage.content[rela.Off:rela.Off+4], targetOffset)
101
102
103 fakeImage.content = append(fakeImage.content, make([]byte, 8)...)
104 }
105
106 break
107 }
108 }
109 return &fakeImage, nil
110 }
111