bpf_load.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <libelf.h>
  6. #include <gelf.h>
  7. #include <errno.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #include <stdbool.h>
  11. #include <linux/bpf.h>
  12. #include <linux/filter.h>
  13. #include "libbpf.h"
  14. #include "bpf_helpers.h"
  15. #include "bpf_load.h"
  16. static char license[128];
  17. static bool processed_sec[128];
  18. int map_fd[MAX_MAPS];
  19. int prog_fd[MAX_PROGS];
  20. int prog_cnt;
  21. static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
  22. {
  23. int fd;
  24. bool is_socket = strncmp(event, "socket", 6) == 0;
  25. if (!is_socket)
  26. /* tracing events tbd */
  27. return -1;
  28. fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER,
  29. prog, size, license);
  30. if (fd < 0) {
  31. printf("bpf_prog_load() err=%d\n%s", errno, bpf_log_buf);
  32. return -1;
  33. }
  34. prog_fd[prog_cnt++] = fd;
  35. return 0;
  36. }
  37. static int load_maps(struct bpf_map_def *maps, int len)
  38. {
  39. int i;
  40. for (i = 0; i < len / sizeof(struct bpf_map_def); i++) {
  41. map_fd[i] = bpf_create_map(maps[i].type,
  42. maps[i].key_size,
  43. maps[i].value_size,
  44. maps[i].max_entries);
  45. if (map_fd[i] < 0)
  46. return 1;
  47. }
  48. return 0;
  49. }
  50. static int get_sec(Elf *elf, int i, GElf_Ehdr *ehdr, char **shname,
  51. GElf_Shdr *shdr, Elf_Data **data)
  52. {
  53. Elf_Scn *scn;
  54. scn = elf_getscn(elf, i);
  55. if (!scn)
  56. return 1;
  57. if (gelf_getshdr(scn, shdr) != shdr)
  58. return 2;
  59. *shname = elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name);
  60. if (!*shname || !shdr->sh_size)
  61. return 3;
  62. *data = elf_getdata(scn, 0);
  63. if (!*data || elf_getdata(scn, *data) != NULL)
  64. return 4;
  65. return 0;
  66. }
  67. static int parse_relo_and_apply(Elf_Data *data, Elf_Data *symbols,
  68. GElf_Shdr *shdr, struct bpf_insn *insn)
  69. {
  70. int i, nrels;
  71. nrels = shdr->sh_size / shdr->sh_entsize;
  72. for (i = 0; i < nrels; i++) {
  73. GElf_Sym sym;
  74. GElf_Rel rel;
  75. unsigned int insn_idx;
  76. gelf_getrel(data, i, &rel);
  77. insn_idx = rel.r_offset / sizeof(struct bpf_insn);
  78. gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &sym);
  79. if (insn[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
  80. printf("invalid relo for insn[%d].code 0x%x\n",
  81. insn_idx, insn[insn_idx].code);
  82. return 1;
  83. }
  84. insn[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
  85. insn[insn_idx].imm = map_fd[sym.st_value / sizeof(struct bpf_map_def)];
  86. }
  87. return 0;
  88. }
  89. int load_bpf_file(char *path)
  90. {
  91. int fd, i;
  92. Elf *elf;
  93. GElf_Ehdr ehdr;
  94. GElf_Shdr shdr, shdr_prog;
  95. Elf_Data *data, *data_prog, *symbols = NULL;
  96. char *shname, *shname_prog;
  97. if (elf_version(EV_CURRENT) == EV_NONE)
  98. return 1;
  99. fd = open(path, O_RDONLY, 0);
  100. if (fd < 0)
  101. return 1;
  102. elf = elf_begin(fd, ELF_C_READ, NULL);
  103. if (!elf)
  104. return 1;
  105. if (gelf_getehdr(elf, &ehdr) != &ehdr)
  106. return 1;
  107. /* scan over all elf sections to get license and map info */
  108. for (i = 1; i < ehdr.e_shnum; i++) {
  109. if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
  110. continue;
  111. if (0) /* helpful for llvm debugging */
  112. printf("section %d:%s data %p size %zd link %d flags %d\n",
  113. i, shname, data->d_buf, data->d_size,
  114. shdr.sh_link, (int) shdr.sh_flags);
  115. if (strcmp(shname, "license") == 0) {
  116. processed_sec[i] = true;
  117. memcpy(license, data->d_buf, data->d_size);
  118. } else if (strcmp(shname, "maps") == 0) {
  119. processed_sec[i] = true;
  120. if (load_maps(data->d_buf, data->d_size))
  121. return 1;
  122. } else if (shdr.sh_type == SHT_SYMTAB) {
  123. symbols = data;
  124. }
  125. }
  126. /* load programs that need map fixup (relocations) */
  127. for (i = 1; i < ehdr.e_shnum; i++) {
  128. if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
  129. continue;
  130. if (shdr.sh_type == SHT_REL) {
  131. struct bpf_insn *insns;
  132. if (get_sec(elf, shdr.sh_info, &ehdr, &shname_prog,
  133. &shdr_prog, &data_prog))
  134. continue;
  135. insns = (struct bpf_insn *) data_prog->d_buf;
  136. processed_sec[shdr.sh_info] = true;
  137. processed_sec[i] = true;
  138. if (parse_relo_and_apply(data, symbols, &shdr, insns))
  139. continue;
  140. if (memcmp(shname_prog, "events/", 7) == 0 ||
  141. memcmp(shname_prog, "socket", 6) == 0)
  142. load_and_attach(shname_prog, insns, data_prog->d_size);
  143. }
  144. }
  145. /* load programs that don't use maps */
  146. for (i = 1; i < ehdr.e_shnum; i++) {
  147. if (processed_sec[i])
  148. continue;
  149. if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
  150. continue;
  151. if (memcmp(shname, "events/", 7) == 0 ||
  152. memcmp(shname, "socket", 6) == 0)
  153. load_and_attach(shname, data->d_buf, data->d_size);
  154. }
  155. close(fd);
  156. return 0;
  157. }