elf_reader.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. package ebpf
  2. import (
  3. "bytes"
  4. "debug/elf"
  5. "encoding/binary"
  6. "fmt"
  7. "io"
  8. "os"
  9. "strings"
  10. "github.com/cilium/ebpf/asm"
  11. "github.com/pkg/errors"
  12. )
  13. type elfCode struct {
  14. *elf.File
  15. symbols []elf.Symbol
  16. symbolsPerSection map[elf.SectionIndex]map[uint64]string
  17. }
  18. // LoadCollectionSpec parses an ELF file into a CollectionSpec.
  19. func LoadCollectionSpec(file string) (*CollectionSpec, error) {
  20. f, err := os.Open(file)
  21. if err != nil {
  22. return nil, err
  23. }
  24. defer f.Close()
  25. spec, err := LoadCollectionSpecFromReader(f)
  26. return spec, errors.Wrapf(err, "file %s", file)
  27. }
  28. // LoadCollectionSpecFromReader parses an ELF file into a CollectionSpec.
  29. func LoadCollectionSpecFromReader(code io.ReaderAt) (*CollectionSpec, error) {
  30. f, err := elf.NewFile(code)
  31. if err != nil {
  32. return nil, err
  33. }
  34. defer f.Close()
  35. symbols, err := f.Symbols()
  36. if err != nil {
  37. return nil, errors.Wrap(err, "load symbols")
  38. }
  39. ec := &elfCode{f, symbols, symbolsPerSection(symbols)}
  40. var licenseSection, versionSection *elf.Section
  41. progSections := make(map[elf.SectionIndex]*elf.Section)
  42. relSections := make(map[elf.SectionIndex]*elf.Section)
  43. mapSections := make(map[elf.SectionIndex]*elf.Section)
  44. for i, sec := range ec.Sections {
  45. switch {
  46. case strings.HasPrefix(sec.Name, "license"):
  47. licenseSection = sec
  48. case strings.HasPrefix(sec.Name, "version"):
  49. versionSection = sec
  50. case strings.HasPrefix(sec.Name, "maps"):
  51. mapSections[elf.SectionIndex(i)] = sec
  52. case sec.Type == elf.SHT_REL:
  53. if int(sec.Info) >= len(ec.Sections) {
  54. return nil, errors.Errorf("found relocation section %v for missing section %v", i, sec.Info)
  55. }
  56. // Store relocations under the section index of the target
  57. idx := elf.SectionIndex(sec.Info)
  58. if relSections[idx] != nil {
  59. return nil, errors.Errorf("section %d has multiple relocation sections", idx)
  60. }
  61. relSections[idx] = sec
  62. case sec.Type == elf.SHT_PROGBITS && (sec.Flags&elf.SHF_EXECINSTR) != 0 && sec.Size > 0:
  63. progSections[elf.SectionIndex(i)] = sec
  64. }
  65. }
  66. license, err := loadLicense(licenseSection)
  67. if err != nil {
  68. return nil, errors.Wrap(err, "load license")
  69. }
  70. version, err := loadVersion(versionSection, ec.ByteOrder)
  71. if err != nil {
  72. return nil, errors.Wrap(err, "load version")
  73. }
  74. maps, err := ec.loadMaps(mapSections)
  75. if err != nil {
  76. return nil, errors.Wrap(err, "load maps")
  77. }
  78. progs, libs, err := ec.loadPrograms(progSections, relSections, license, version)
  79. if err != nil {
  80. return nil, errors.Wrap(err, "load programs")
  81. }
  82. if len(libs) > 0 {
  83. for name, prog := range progs {
  84. prog.Instructions, err = link(prog.Instructions, libs...)
  85. if err != nil {
  86. return nil, errors.Wrapf(err, "program %s", name)
  87. }
  88. }
  89. }
  90. return &CollectionSpec{maps, progs}, nil
  91. }
  92. func loadLicense(sec *elf.Section) (string, error) {
  93. if sec == nil {
  94. return "", errors.Errorf("missing license section")
  95. }
  96. data, err := sec.Data()
  97. if err != nil {
  98. return "", errors.Wrapf(err, "section %s", sec.Name)
  99. }
  100. return string(bytes.TrimRight(data, "\000")), nil
  101. }
  102. func loadVersion(sec *elf.Section, bo binary.ByteOrder) (uint32, error) {
  103. if sec == nil {
  104. return 0, nil
  105. }
  106. var version uint32
  107. err := binary.Read(sec.Open(), bo, &version)
  108. return version, errors.Wrapf(err, "section %s", sec.Name)
  109. }
  110. func (ec *elfCode) loadPrograms(progSections, relSections map[elf.SectionIndex]*elf.Section, license string, version uint32) (map[string]*ProgramSpec, []asm.Instructions, error) {
  111. var (
  112. progs = make(map[string]*ProgramSpec)
  113. libs []asm.Instructions
  114. )
  115. for idx, prog := range progSections {
  116. syms := ec.symbolsPerSection[idx]
  117. if len(syms) == 0 {
  118. return nil, nil, errors.Errorf("section %v: missing symbols", prog.Name)
  119. }
  120. funcSym := syms[0]
  121. if funcSym == "" {
  122. return nil, nil, errors.Errorf("section %v: no label at start", prog.Name)
  123. }
  124. rels, err := ec.loadRelocations(relSections[idx])
  125. if err != nil {
  126. return nil, nil, errors.Wrapf(err, "program %s: can't load relocations", funcSym)
  127. }
  128. insns, err := ec.loadInstructions(prog, syms, rels)
  129. if err != nil {
  130. return nil, nil, errors.Wrapf(err, "program %s: can't unmarshal instructions", funcSym)
  131. }
  132. if progType, attachType := getProgType(prog.Name); progType == UnspecifiedProgram {
  133. // There is no single name we can use for "library" sections,
  134. // since they may contain multiple functions. We'll decode the
  135. // labels they contain later on, and then link sections that way.
  136. libs = append(libs, insns)
  137. } else {
  138. progs[funcSym] = &ProgramSpec{
  139. Name: funcSym,
  140. Type: progType,
  141. AttachType: attachType,
  142. License: license,
  143. KernelVersion: version,
  144. Instructions: insns,
  145. }
  146. }
  147. }
  148. return progs, libs, nil
  149. }
  150. func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations map[uint64]string) (asm.Instructions, error) {
  151. var (
  152. r = section.Open()
  153. insns asm.Instructions
  154. ins asm.Instruction
  155. offset uint64
  156. )
  157. for {
  158. n, err := ins.Unmarshal(r, ec.ByteOrder)
  159. if err == io.EOF {
  160. return insns, nil
  161. }
  162. if err != nil {
  163. return nil, errors.Wrapf(err, "offset %d", offset)
  164. }
  165. ins.Symbol = symbols[offset]
  166. ins.Reference = relocations[offset]
  167. insns = append(insns, ins)
  168. offset += n
  169. }
  170. }
  171. func (ec *elfCode) loadMaps(mapSections map[elf.SectionIndex]*elf.Section) (map[string]*MapSpec, error) {
  172. var (
  173. maps = make(map[string]*MapSpec)
  174. b = make([]byte, 1)
  175. )
  176. for idx, sec := range mapSections {
  177. syms := ec.symbolsPerSection[idx]
  178. if len(syms) == 0 {
  179. return nil, errors.Errorf("section %v: no symbols", sec.Name)
  180. }
  181. if sec.Size%uint64(len(syms)) != 0 {
  182. return nil, errors.Errorf("section %v: map descriptors are not of equal size", sec.Name)
  183. }
  184. var (
  185. r = sec.Open()
  186. size = sec.Size / uint64(len(syms))
  187. )
  188. for i, offset := 0, uint64(0); i < len(syms); i, offset = i+1, offset+size {
  189. mapSym := syms[offset]
  190. if mapSym == "" {
  191. fmt.Println(syms)
  192. return nil, errors.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset)
  193. }
  194. if maps[mapSym] != nil {
  195. return nil, errors.Errorf("section %v: map %v already exists", sec.Name, mapSym)
  196. }
  197. lr := io.LimitReader(r, int64(size))
  198. var spec MapSpec
  199. switch {
  200. case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil:
  201. return nil, errors.Errorf("map %v: missing type", mapSym)
  202. case binary.Read(lr, ec.ByteOrder, &spec.KeySize) != nil:
  203. return nil, errors.Errorf("map %v: missing key size", mapSym)
  204. case binary.Read(lr, ec.ByteOrder, &spec.ValueSize) != nil:
  205. return nil, errors.Errorf("map %v: missing value size", mapSym)
  206. case binary.Read(lr, ec.ByteOrder, &spec.MaxEntries) != nil:
  207. return nil, errors.Errorf("map %v: missing max entries", mapSym)
  208. case binary.Read(lr, ec.ByteOrder, &spec.Flags) != nil:
  209. return nil, errors.Errorf("map %v: missing flags", mapSym)
  210. }
  211. for {
  212. _, err := lr.Read(b)
  213. if err == io.EOF {
  214. break
  215. }
  216. if err != nil {
  217. return nil, err
  218. }
  219. if b[0] != 0 {
  220. return nil, errors.Errorf("map %v: unknown and non-zero fields in definition", mapSym)
  221. }
  222. }
  223. maps[mapSym] = &spec
  224. }
  225. }
  226. return maps, nil
  227. }
  228. func getProgType(v string) (ProgramType, AttachType) {
  229. types := map[string]ProgramType{
  230. // From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c#n3568
  231. "socket": SocketFilter,
  232. "seccomp": SocketFilter,
  233. "kprobe/": Kprobe,
  234. "kretprobe/": Kprobe,
  235. "tracepoint/": TracePoint,
  236. "xdp": XDP,
  237. "perf_event": PerfEvent,
  238. "sockops": SockOps,
  239. "sk_skb": SkSKB,
  240. "sk_msg": SkMsg,
  241. "lirc_mode2": LircMode2,
  242. "flow_dissector": FlowDissector,
  243. "cgroup_skb/": CGroupSKB,
  244. "cgroup/dev": CGroupDevice,
  245. "cgroup/skb": CGroupSKB,
  246. "cgroup/sock": CGroupSock,
  247. "cgroup/post_bind": CGroupSock,
  248. "cgroup/bind": CGroupSockAddr,
  249. "cgroup/connect": CGroupSockAddr,
  250. "cgroup/sendmsg": CGroupSockAddr,
  251. "cgroup/recvmsg": CGroupSockAddr,
  252. "cgroup/sysctl": CGroupSysctl,
  253. "cgroup/getsockopt": CGroupSockopt,
  254. "cgroup/setsockopt": CGroupSockopt,
  255. "classifier": SchedCLS,
  256. "action": SchedACT,
  257. }
  258. attachTypes := map[string]AttachType{
  259. "cgroup_skb/ingress": AttachCGroupInetIngress,
  260. "cgroup_skb/egress": AttachCGroupInetEgress,
  261. "cgroup/sock": AttachCGroupInetSockCreate,
  262. "cgroup/post_bind4": AttachCGroupInet4PostBind,
  263. "cgroup/post_bind6": AttachCGroupInet6PostBind,
  264. "cgroup/dev": AttachCGroupDevice,
  265. "sockops": AttachCGroupSockOps,
  266. "sk_skb/stream_parser": AttachSkSKBStreamParser,
  267. "sk_skb/stream_verdict": AttachSkSKBStreamVerdict,
  268. "sk_msg": AttachSkSKBStreamVerdict,
  269. "lirc_mode2": AttachLircMode2,
  270. "flow_dissector": AttachFlowDissector,
  271. "cgroup/bind4": AttachCGroupInet4Bind,
  272. "cgroup/bind6": AttachCGroupInet6Bind,
  273. "cgroup/connect4": AttachCGroupInet4Connect,
  274. "cgroup/connect6": AttachCGroupInet6Connect,
  275. "cgroup/sendmsg4": AttachCGroupUDP4Sendmsg,
  276. "cgroup/sendmsg6": AttachCGroupUDP6Sendmsg,
  277. "cgroup/recvmsg4": AttachCGroupUDP4Recvmsg,
  278. "cgroup/recvmsg6": AttachCGroupUDP6Recvmsg,
  279. "cgroup/sysctl": AttachCGroupSysctl,
  280. "cgroup/getsockopt": AttachCGroupGetsockopt,
  281. "cgroup/setsockopt": AttachCGroupSetsockopt,
  282. }
  283. attachType := AttachNone
  284. for k, t := range attachTypes {
  285. if strings.HasPrefix(v, k) {
  286. attachType = t
  287. }
  288. }
  289. for k, t := range types {
  290. if strings.HasPrefix(v, k) {
  291. return t, attachType
  292. }
  293. }
  294. return UnspecifiedProgram, AttachNone
  295. }
  296. func (ec *elfCode) loadRelocations(sec *elf.Section) (map[uint64]string, error) {
  297. rels := make(map[uint64]string)
  298. if sec == nil {
  299. return rels, nil
  300. }
  301. if sec.Entsize < 16 {
  302. return nil, errors.New("rels are less than 16 bytes")
  303. }
  304. r := sec.Open()
  305. for off := uint64(0); off < sec.Size; off += sec.Entsize {
  306. ent := io.LimitReader(r, int64(sec.Entsize))
  307. var rel elf.Rel64
  308. if binary.Read(ent, ec.ByteOrder, &rel) != nil {
  309. return nil, errors.Errorf("can't parse relocation at offset %v", off)
  310. }
  311. symNo := int(elf.R_SYM64(rel.Info) - 1)
  312. if symNo >= len(ec.symbols) {
  313. return nil, errors.Errorf("relocation at offset %d: symbol %v doesnt exist", off, symNo)
  314. }
  315. rels[rel.Off] = ec.symbols[symNo].Name
  316. }
  317. return rels, nil
  318. }
  319. func symbolsPerSection(symbols []elf.Symbol) map[elf.SectionIndex]map[uint64]string {
  320. result := make(map[elf.SectionIndex]map[uint64]string)
  321. for i, sym := range symbols {
  322. switch elf.ST_TYPE(sym.Info) {
  323. case elf.STT_NOTYPE:
  324. // Older versions of LLVM doesn't tag
  325. // symbols correctly.
  326. break
  327. case elf.STT_OBJECT:
  328. break
  329. case elf.STT_FUNC:
  330. break
  331. default:
  332. continue
  333. }
  334. if sym.Name == "" {
  335. continue
  336. }
  337. idx := sym.Section
  338. if _, ok := result[idx]; !ok {
  339. result[idx] = make(map[uint64]string)
  340. }
  341. result[idx][sym.Value] = symbols[i].Name
  342. }
  343. return result
  344. }