blob: d8d6eb5801884217dc1781bbaf65c1d228260c41 [file] [log] [blame]
Wang Nan1b76c132015-07-01 02:13:51 +00001/*
2 * Common eBPF ELF object loading operations.
3 *
4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
6 * Copyright (C) 2015 Huawei Inc.
7 */
8
9#include <stdlib.h>
Wang Nanb3f59d62015-07-01 02:13:52 +000010#include <stdio.h>
11#include <stdarg.h>
12#include <string.h>
Wang Nan1b76c132015-07-01 02:13:51 +000013#include <unistd.h>
Wang Nan1a5e3fb2015-07-01 02:13:53 +000014#include <fcntl.h>
15#include <errno.h>
Wang Nan1b76c132015-07-01 02:13:51 +000016#include <asm/unistd.h>
17#include <linux/bpf.h>
Wang Nan1a5e3fb2015-07-01 02:13:53 +000018#include <libelf.h>
19#include <gelf.h>
Wang Nan1b76c132015-07-01 02:13:51 +000020
21#include "libbpf.h"
Wang Nanb3f59d62015-07-01 02:13:52 +000022
23#define __printf(a, b) __attribute__((format(printf, a, b)))
24
25__printf(1, 2)
26static int __base_pr(const char *format, ...)
27{
28 va_list args;
29 int err;
30
31 va_start(args, format);
32 err = vfprintf(stderr, format, args);
33 va_end(args);
34 return err;
35}
36
37static __printf(1, 2) libbpf_print_fn_t __pr_warning = __base_pr;
38static __printf(1, 2) libbpf_print_fn_t __pr_info = __base_pr;
39static __printf(1, 2) libbpf_print_fn_t __pr_debug;
40
41#define __pr(func, fmt, ...) \
42do { \
43 if ((func)) \
44 (func)("libbpf: " fmt, ##__VA_ARGS__); \
45} while (0)
46
47#define pr_warning(fmt, ...) __pr(__pr_warning, fmt, ##__VA_ARGS__)
48#define pr_info(fmt, ...) __pr(__pr_info, fmt, ##__VA_ARGS__)
49#define pr_debug(fmt, ...) __pr(__pr_debug, fmt, ##__VA_ARGS__)
50
51void libbpf_set_print(libbpf_print_fn_t warn,
52 libbpf_print_fn_t info,
53 libbpf_print_fn_t debug)
54{
55 __pr_warning = warn;
56 __pr_info = info;
57 __pr_debug = debug;
58}
Wang Nan1a5e3fb2015-07-01 02:13:53 +000059
60/* Copied from tools/perf/util/util.h */
61#ifndef zfree
62# define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
63#endif
64
65#ifndef zclose
66# define zclose(fd) ({ \
67 int ___err = 0; \
68 if ((fd) >= 0) \
69 ___err = close((fd)); \
70 fd = -1; \
71 ___err; })
72#endif
73
74#ifdef HAVE_LIBELF_MMAP_SUPPORT
75# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ_MMAP
76#else
77# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
78#endif
79
80struct bpf_object {
81 /*
82 * Information when doing elf related work. Only valid if fd
83 * is valid.
84 */
85 struct {
86 int fd;
Wang Nan6c956392015-07-01 02:13:54 +000087 void *obj_buf;
88 size_t obj_buf_sz;
Wang Nan1a5e3fb2015-07-01 02:13:53 +000089 Elf *elf;
90 GElf_Ehdr ehdr;
91 } efile;
92 char path[];
93};
94#define obj_elf_valid(o) ((o)->efile.elf)
95
Wang Nan6c956392015-07-01 02:13:54 +000096static struct bpf_object *bpf_object__new(const char *path,
97 void *obj_buf,
98 size_t obj_buf_sz)
Wang Nan1a5e3fb2015-07-01 02:13:53 +000099{
100 struct bpf_object *obj;
101
102 obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1);
103 if (!obj) {
104 pr_warning("alloc memory failed for %s\n", path);
105 return NULL;
106 }
107
108 strcpy(obj->path, path);
109 obj->efile.fd = -1;
Wang Nan6c956392015-07-01 02:13:54 +0000110
111 /*
112 * Caller of this function should also calls
113 * bpf_object__elf_finish() after data collection to return
114 * obj_buf to user. If not, we should duplicate the buffer to
115 * avoid user freeing them before elf finish.
116 */
117 obj->efile.obj_buf = obj_buf;
118 obj->efile.obj_buf_sz = obj_buf_sz;
119
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000120 return obj;
121}
122
123static void bpf_object__elf_finish(struct bpf_object *obj)
124{
125 if (!obj_elf_valid(obj))
126 return;
127
128 if (obj->efile.elf) {
129 elf_end(obj->efile.elf);
130 obj->efile.elf = NULL;
131 }
132 zclose(obj->efile.fd);
Wang Nan6c956392015-07-01 02:13:54 +0000133 obj->efile.obj_buf = NULL;
134 obj->efile.obj_buf_sz = 0;
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000135}
136
137static int bpf_object__elf_init(struct bpf_object *obj)
138{
139 int err = 0;
140 GElf_Ehdr *ep;
141
142 if (obj_elf_valid(obj)) {
143 pr_warning("elf init: internal error\n");
144 return -EEXIST;
145 }
146
Wang Nan6c956392015-07-01 02:13:54 +0000147 if (obj->efile.obj_buf_sz > 0) {
148 /*
149 * obj_buf should have been validated by
150 * bpf_object__open_buffer().
151 */
152 obj->efile.elf = elf_memory(obj->efile.obj_buf,
153 obj->efile.obj_buf_sz);
154 } else {
155 obj->efile.fd = open(obj->path, O_RDONLY);
156 if (obj->efile.fd < 0) {
157 pr_warning("failed to open %s: %s\n", obj->path,
158 strerror(errno));
159 return -errno;
160 }
161
162 obj->efile.elf = elf_begin(obj->efile.fd,
163 LIBBPF_ELF_C_READ_MMAP,
164 NULL);
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000165 }
166
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000167 if (!obj->efile.elf) {
168 pr_warning("failed to open %s as ELF file\n",
169 obj->path);
170 err = -EINVAL;
171 goto errout;
172 }
173
174 if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) {
175 pr_warning("failed to get EHDR from %s\n",
176 obj->path);
177 err = -EINVAL;
178 goto errout;
179 }
180 ep = &obj->efile.ehdr;
181
182 if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
183 pr_warning("%s is not an eBPF object file\n",
184 obj->path);
185 err = -EINVAL;
186 goto errout;
187 }
188
189 return 0;
190errout:
191 bpf_object__elf_finish(obj);
192 return err;
193}
194
Wang Nancc4228d2015-07-01 02:13:55 +0000195static int
196bpf_object__check_endianness(struct bpf_object *obj)
197{
198 static unsigned int const endian = 1;
199
200 switch (obj->efile.ehdr.e_ident[EI_DATA]) {
201 case ELFDATA2LSB:
202 /* We are big endian, BPF obj is little endian. */
203 if (*(unsigned char const *)&endian != 1)
204 goto mismatch;
205 break;
206
207 case ELFDATA2MSB:
208 /* We are little endian, BPF obj is big endian. */
209 if (*(unsigned char const *)&endian != 0)
210 goto mismatch;
211 break;
212 default:
213 return -EINVAL;
214 }
215
216 return 0;
217
218mismatch:
219 pr_warning("Error: endianness mismatch.\n");
220 return -EINVAL;
221}
222
Wang Nan29603662015-07-01 02:13:56 +0000223static int bpf_object__elf_collect(struct bpf_object *obj)
224{
225 Elf *elf = obj->efile.elf;
226 GElf_Ehdr *ep = &obj->efile.ehdr;
227 Elf_Scn *scn = NULL;
228 int idx = 0, err = 0;
229
230 /* Elf is corrupted/truncated, avoid calling elf_strptr. */
231 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
232 pr_warning("failed to get e_shstrndx from %s\n",
233 obj->path);
234 return -EINVAL;
235 }
236
237 while ((scn = elf_nextscn(elf, scn)) != NULL) {
238 char *name;
239 GElf_Shdr sh;
240 Elf_Data *data;
241
242 idx++;
243 if (gelf_getshdr(scn, &sh) != &sh) {
244 pr_warning("failed to get section header from %s\n",
245 obj->path);
246 err = -EINVAL;
247 goto out;
248 }
249
250 name = elf_strptr(elf, ep->e_shstrndx, sh.sh_name);
251 if (!name) {
252 pr_warning("failed to get section name from %s\n",
253 obj->path);
254 err = -EINVAL;
255 goto out;
256 }
257
258 data = elf_getdata(scn, 0);
259 if (!data) {
260 pr_warning("failed to get section data from %s(%s)\n",
261 name, obj->path);
262 err = -EINVAL;
263 goto out;
264 }
265 pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n",
266 name, (unsigned long)data->d_size,
267 (int)sh.sh_link, (unsigned long)sh.sh_flags,
268 (int)sh.sh_type);
269 }
270out:
271 return err;
272}
273
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000274static struct bpf_object *
Wang Nan6c956392015-07-01 02:13:54 +0000275__bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz)
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000276{
277 struct bpf_object *obj;
278
279 if (elf_version(EV_CURRENT) == EV_NONE) {
280 pr_warning("failed to init libelf for %s\n", path);
281 return NULL;
282 }
283
Wang Nan6c956392015-07-01 02:13:54 +0000284 obj = bpf_object__new(path, obj_buf, obj_buf_sz);
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000285 if (!obj)
286 return NULL;
287
288 if (bpf_object__elf_init(obj))
289 goto out;
Wang Nancc4228d2015-07-01 02:13:55 +0000290 if (bpf_object__check_endianness(obj))
291 goto out;
Wang Nan29603662015-07-01 02:13:56 +0000292 if (bpf_object__elf_collect(obj))
293 goto out;
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000294
295 bpf_object__elf_finish(obj);
296 return obj;
297out:
298 bpf_object__close(obj);
299 return NULL;
300}
301
302struct bpf_object *bpf_object__open(const char *path)
303{
304 /* param validation */
305 if (!path)
306 return NULL;
307
308 pr_debug("loading %s\n", path);
309
Wang Nan6c956392015-07-01 02:13:54 +0000310 return __bpf_object__open(path, NULL, 0);
311}
312
313struct bpf_object *bpf_object__open_buffer(void *obj_buf,
314 size_t obj_buf_sz)
315{
316 /* param validation */
317 if (!obj_buf || obj_buf_sz <= 0)
318 return NULL;
319
320 pr_debug("loading object from buffer\n");
321
322 return __bpf_object__open("[buffer]", obj_buf, obj_buf_sz);
Wang Nan1a5e3fb2015-07-01 02:13:53 +0000323}
324
325void bpf_object__close(struct bpf_object *obj)
326{
327 if (!obj)
328 return;
329
330 bpf_object__elf_finish(obj);
331
332 free(obj);
333}