11 #include <linux/bpf.h>
12 #include <linux/filter.h>
14 #include "bpf_helpers.h"
17 static char license
[128];
18 static bool processed_sec
[128];
20 int prog_fd
[MAX_PROGS
];
23 static int load_and_attach(const char *event
, struct bpf_insn
*prog
, int size
)
26 bool is_socket
= strncmp(event
, "socket", 6) == 0;
29 /* tracing events tbd */
32 fd
= bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER
,
36 printf("bpf_prog_load() err=%d\n%s", errno
, bpf_log_buf
);
40 prog_fd
[prog_cnt
++] = fd
;
45 static int load_maps(struct bpf_map_def
*maps
, int len
)
49 for (i
= 0; i
< len
/ sizeof(struct bpf_map_def
); i
++) {
51 map_fd
[i
] = bpf_create_map(maps
[i
].type
,
61 static int get_sec(Elf
*elf
, int i
, GElf_Ehdr
*ehdr
, char **shname
,
62 GElf_Shdr
*shdr
, Elf_Data
**data
)
66 scn
= elf_getscn(elf
, i
);
70 if (gelf_getshdr(scn
, shdr
) != shdr
)
73 *shname
= elf_strptr(elf
, ehdr
->e_shstrndx
, shdr
->sh_name
);
74 if (!*shname
|| !shdr
->sh_size
)
77 *data
= elf_getdata(scn
, 0);
78 if (!*data
|| elf_getdata(scn
, *data
) != NULL
)
84 static int parse_relo_and_apply(Elf_Data
*data
, Elf_Data
*symbols
,
85 GElf_Shdr
*shdr
, struct bpf_insn
*insn
)
89 nrels
= shdr
->sh_size
/ shdr
->sh_entsize
;
91 for (i
= 0; i
< nrels
; i
++) {
94 unsigned int insn_idx
;
96 gelf_getrel(data
, i
, &rel
);
98 insn_idx
= rel
.r_offset
/ sizeof(struct bpf_insn
);
100 gelf_getsym(symbols
, GELF_R_SYM(rel
.r_info
), &sym
);
102 if (insn
[insn_idx
].code
!= (BPF_LD
| BPF_IMM
| BPF_DW
)) {
103 printf("invalid relo for insn[%d].code 0x%x\n",
104 insn_idx
, insn
[insn_idx
].code
);
107 insn
[insn_idx
].src_reg
= BPF_PSEUDO_MAP_FD
;
108 insn
[insn_idx
].imm
= map_fd
[sym
.st_value
/ sizeof(struct bpf_map_def
)];
114 int load_bpf_file(char *path
)
119 GElf_Shdr shdr
, shdr_prog
;
120 Elf_Data
*data
, *data_prog
, *symbols
= NULL
;
121 char *shname
, *shname_prog
;
123 if (elf_version(EV_CURRENT
) == EV_NONE
)
126 fd
= open(path
, O_RDONLY
, 0);
130 elf
= elf_begin(fd
, ELF_C_READ
, NULL
);
135 if (gelf_getehdr(elf
, &ehdr
) != &ehdr
)
138 /* scan over all elf sections to get license and map info */
139 for (i
= 1; i
< ehdr
.e_shnum
; i
++) {
141 if (get_sec(elf
, i
, &ehdr
, &shname
, &shdr
, &data
))
144 if (0) /* helpful for llvm debugging */
145 printf("section %d:%s data %p size %zd link %d flags %d\n",
146 i
, shname
, data
->d_buf
, data
->d_size
,
147 shdr
.sh_link
, (int) shdr
.sh_flags
);
149 if (strcmp(shname
, "license") == 0) {
150 processed_sec
[i
] = true;
151 memcpy(license
, data
->d_buf
, data
->d_size
);
152 } else if (strcmp(shname
, "maps") == 0) {
153 processed_sec
[i
] = true;
154 if (load_maps(data
->d_buf
, data
->d_size
))
156 } else if (shdr
.sh_type
== SHT_SYMTAB
) {
161 /* load programs that need map fixup (relocations) */
162 for (i
= 1; i
< ehdr
.e_shnum
; i
++) {
164 if (get_sec(elf
, i
, &ehdr
, &shname
, &shdr
, &data
))
166 if (shdr
.sh_type
== SHT_REL
) {
167 struct bpf_insn
*insns
;
169 if (get_sec(elf
, shdr
.sh_info
, &ehdr
, &shname_prog
,
170 &shdr_prog
, &data_prog
))
173 insns
= (struct bpf_insn
*) data_prog
->d_buf
;
175 processed_sec
[shdr
.sh_info
] = true;
176 processed_sec
[i
] = true;
178 if (parse_relo_and_apply(data
, symbols
, &shdr
, insns
))
181 if (memcmp(shname_prog
, "events/", 7) == 0 ||
182 memcmp(shname_prog
, "socket", 6) == 0)
183 load_and_attach(shname_prog
, insns
, data_prog
->d_size
);
187 /* load programs that don't use maps */
188 for (i
= 1; i
< ehdr
.e_shnum
; i
++) {
190 if (processed_sec
[i
])
193 if (get_sec(elf
, i
, &ehdr
, &shname
, &shdr
, &data
))
196 if (memcmp(shname
, "events/", 7) == 0 ||
197 memcmp(shname
, "socket", 6) == 0)
198 load_and_attach(shname
, data
->d_buf
, data
->d_size
);