1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
13 #include <sys/types.h>
15 #include <sys/queue.h>
20 #include <rte_common.h>
22 #include <rte_debug.h>
23 #include <rte_memory.h>
25 #include <rte_byteorder.h>
26 #include <rte_errno.h>
30 /* To overcome compatibility issue */
36 bpf_find_xsym(const char *sn, enum rte_bpf_xtype type,
37 const struct rte_bpf_xsym fp[], uint32_t fn)
41 if (sn == NULL || fp == NULL)
44 for (i = 0; i != fn; i++) {
45 if (fp[i].type == type && strcmp(sn, fp[i].name) == 0)
49 return (i != fn) ? i : UINT32_MAX;
53 * update BPF code at offset *ofs* with a proper address(index) for external
57 resolve_xsym(const char *sn, size_t ofs, struct ebpf_insn *ins, size_t ins_sz,
58 const struct rte_bpf_prm *prm)
61 enum rte_bpf_xtype type;
63 if (ofs % sizeof(ins[0]) != 0 || ofs >= ins_sz)
66 idx = ofs / sizeof(ins[0]);
67 if (ins[idx].code == (BPF_JMP | EBPF_CALL))
68 type = RTE_BPF_XTYPE_FUNC;
69 else if (ins[idx].code == (BPF_LD | BPF_IMM | EBPF_DW) &&
70 ofs < ins_sz - sizeof(ins[idx]))
71 type = RTE_BPF_XTYPE_VAR;
75 fidx = bpf_find_xsym(sn, type, prm->xsym, prm->nb_xsym);
76 if (fidx == UINT32_MAX)
79 /* for function we just need an index in our xsym table */
80 if (type == RTE_BPF_XTYPE_FUNC)
82 /* for variable we need to store its absolute address */
84 ins[idx].imm = (uintptr_t)prm->xsym[fidx].var.val;
86 (uint64_t)(uintptr_t)prm->xsym[fidx].var.val >> 32;
93 check_elf_header(const Elf64_Ehdr *eh)
99 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
100 if (eh->e_ident[EI_DATA] != ELFDATA2LSB)
102 if (eh->e_ident[EI_DATA] != ELFDATA2MSB)
104 err = "not native byte order";
105 else if (eh->e_ident[EI_OSABI] != ELFOSABI_NONE)
106 err = "unexpected OS ABI";
107 else if (eh->e_type != ET_REL)
108 err = "unexpected ELF type";
109 else if (eh->e_machine != EM_NONE && eh->e_machine != EM_BPF)
110 err = "unexpected machine type";
113 RTE_BPF_LOG(ERR, "%s(): %s\n", __func__, err);
121 * helper function, find executable section by name.
124 find_elf_code(Elf *elf, const char *section, Elf_Data **psd, size_t *pidx)
127 const Elf64_Ehdr *eh;
128 const Elf64_Shdr *sh;
133 eh = elf64_getehdr(elf);
136 RTE_BPF_LOG(ERR, "%s(%p, %s) error code: %d(%s)\n",
137 __func__, elf, section, rc, elf_errmsg(rc));
141 if (check_elf_header(eh) != 0)
144 /* find given section by name */
145 for (sc = elf_nextscn(elf, NULL); sc != NULL;
146 sc = elf_nextscn(elf, sc)) {
147 sh = elf64_getshdr(sc);
148 sn = elf_strptr(elf, eh->e_shstrndx, sh->sh_name);
149 if (sn != NULL && strcmp(section, sn) == 0 &&
150 sh->sh_type == SHT_PROGBITS &&
151 sh->sh_flags == (SHF_ALLOC | SHF_EXECINSTR))
155 sd = elf_getdata(sc, NULL);
156 if (sd == NULL || sd->d_size == 0 ||
157 sd->d_size % sizeof(struct ebpf_insn) != 0) {
159 RTE_BPF_LOG(ERR, "%s(%p, %s) error code: %d(%s)\n",
160 __func__, elf, section, rc, elf_errmsg(rc));
165 *pidx = elf_ndxscn(sc);
170 * helper function to process data from relocation table.
173 process_reloc(Elf *elf, size_t sym_idx, Elf64_Rel *re, size_t re_sz,
174 struct ebpf_insn *ins, size_t ins_sz, const struct rte_bpf_prm *prm)
180 const Elf64_Ehdr *eh;
185 eh = elf64_getehdr(elf);
187 /* get symtable by section index */
188 sc = elf_getscn(elf, sym_idx);
189 sd = elf_getdata(sc, NULL);
194 n = re_sz / sizeof(re[0]);
195 for (i = 0; i != n; i++) {
197 ofs = re[i].r_offset;
199 /* retrieve index in the symtable */
200 sym = ELF64_R_SYM(re[i].r_info);
201 if (sym * sizeof(sm[0]) >= sd->d_size)
204 sn = elf_strptr(elf, eh->e_shstrndx, sm[sym].st_name);
206 rc = resolve_xsym(sn, ofs, ins, ins_sz, prm);
209 "resolve_xsym(%s, %zu) error code: %d\n",
219 * helper function, find relocation information (if any)
220 * and update bpf code.
223 elf_reloc_code(Elf *elf, Elf_Data *ed, size_t sidx,
224 const struct rte_bpf_prm *prm)
228 const Elf64_Shdr *sh;
234 /* walk through all sections */
235 for (sc = elf_nextscn(elf, NULL); sc != NULL && rc == 0;
236 sc = elf_nextscn(elf, sc)) {
238 sh = elf64_getshdr(sc);
240 /* relocation data for our code section */
241 if (sh->sh_type == SHT_REL && sh->sh_info == sidx) {
242 sd = elf_getdata(sc, NULL);
243 if (sd == NULL || sd->d_size == 0 ||
244 sd->d_size % sizeof(re[0]) != 0)
246 rc = process_reloc(elf, sh->sh_link,
247 sd->d_buf, sd->d_size, ed->d_buf, ed->d_size,
255 static struct rte_bpf *
256 bpf_load_elf(const struct rte_bpf_prm *prm, int32_t fd, const char *section)
263 struct rte_bpf_prm np;
265 elf_version(EV_CURRENT);
266 elf = elf_begin(fd, ELF_C_READ, NULL);
268 rc = find_elf_code(elf, section, &sd, &sidx);
270 rc = elf_reloc_code(elf, sd, sidx, prm);
275 np.nb_ins = sd->d_size / sizeof(struct ebpf_insn);
276 bpf = rte_bpf_load(&np);
286 __rte_experimental struct rte_bpf *
287 rte_bpf_elf_load(const struct rte_bpf_prm *prm, const char *fname,
293 if (prm == NULL || fname == NULL || sname == NULL) {
298 fd = open(fname, O_RDONLY);
301 RTE_BPF_LOG(ERR, "%s(%s) error code: %d(%s)\n",
302 __func__, fname, rc, strerror(rc));
307 bpf = bpf_load_elf(prm, fd, sname);
312 "%s(fname=\"%s\", sname=\"%s\") failed, "
314 __func__, fname, sname, rte_errno);
318 RTE_BPF_LOG(INFO, "%s(fname=\"%s\", sname=\"%s\") "
319 "successfully creates %p(jit={.func=%p,.sz=%zu});\n",
320 __func__, fname, sname, bpf, bpf->jit.func, bpf->jit.sz);