libbpf.c 8.8 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * Common eBPF ELF object loading operations.
 *
 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
 * Copyright (C) 2015 Huawei Inc.
 */

#include <stdlib.h>
10 11 12
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
13
#include <unistd.h>
14 15
#include <fcntl.h>
#include <errno.h>
16
#include <asm/unistd.h>
17
#include <linux/kernel.h>
18
#include <linux/bpf.h>
19 20
#include <libelf.h>
#include <gelf.h>
21 22

#include "libbpf.h"
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59

#define __printf(a, b)	__attribute__((format(printf, a, b)))

__printf(1, 2)
static int __base_pr(const char *format, ...)
{
	va_list args;
	int err;

	va_start(args, format);
	err = vfprintf(stderr, format, args);
	va_end(args);
	return err;
}

static __printf(1, 2) libbpf_print_fn_t __pr_warning = __base_pr;
static __printf(1, 2) libbpf_print_fn_t __pr_info = __base_pr;
static __printf(1, 2) libbpf_print_fn_t __pr_debug;

#define __pr(func, fmt, ...)	\
do {				\
	if ((func))		\
		(func)("libbpf: " fmt, ##__VA_ARGS__); \
} while (0)

#define pr_warning(fmt, ...)	__pr(__pr_warning, fmt, ##__VA_ARGS__)
#define pr_info(fmt, ...)	__pr(__pr_info, fmt, ##__VA_ARGS__)
#define pr_debug(fmt, ...)	__pr(__pr_debug, fmt, ##__VA_ARGS__)

void libbpf_set_print(libbpf_print_fn_t warn,
		      libbpf_print_fn_t info,
		      libbpf_print_fn_t debug)
{
	__pr_warning = warn;
	__pr_info = info;
	__pr_debug = debug;
}
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81

/* Copied from tools/perf/util/util.h */
#ifndef zfree
# define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
#endif

#ifndef zclose
# define zclose(fd) ({			\
	int ___err = 0;			\
	if ((fd) >= 0)			\
		___err = close((fd));	\
	fd = -1;			\
	___err; })
#endif

#ifdef HAVE_LIBELF_MMAP_SUPPORT
# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ_MMAP
#else
# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
#endif

struct bpf_object {
82 83
	char license[64];
	u32 kern_version;
84 85 86
	void *maps_buf;
	size_t maps_buf_sz;

87 88 89 90 91 92
	/*
	 * Information when doing elf related work. Only valid if fd
	 * is valid.
	 */
	struct {
		int fd;
93 94
		void *obj_buf;
		size_t obj_buf_sz;
95 96
		Elf *elf;
		GElf_Ehdr ehdr;
97
		Elf_Data *symbols;
98 99 100 101 102
	} efile;
	char path[];
};
#define obj_elf_valid(o)	((o)->efile.elf)

103 104 105
static struct bpf_object *bpf_object__new(const char *path,
					  void *obj_buf,
					  size_t obj_buf_sz)
106 107 108 109 110 111 112 113 114 115 116
{
	struct bpf_object *obj;

	obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1);
	if (!obj) {
		pr_warning("alloc memory failed for %s\n", path);
		return NULL;
	}

	strcpy(obj->path, path);
	obj->efile.fd = -1;
117 118 119 120 121 122 123 124 125 126

	/*
	 * Caller of this function should also calls
	 * bpf_object__elf_finish() after data collection to return
	 * obj_buf to user. If not, we should duplicate the buffer to
	 * avoid user freeing them before elf finish.
	 */
	obj->efile.obj_buf = obj_buf;
	obj->efile.obj_buf_sz = obj_buf_sz;

127 128 129 130 131 132 133 134 135 136 137 138
	return obj;
}

static void bpf_object__elf_finish(struct bpf_object *obj)
{
	if (!obj_elf_valid(obj))
		return;

	if (obj->efile.elf) {
		elf_end(obj->efile.elf);
		obj->efile.elf = NULL;
	}
139
	obj->efile.symbols = NULL;
140
	zclose(obj->efile.fd);
141 142
	obj->efile.obj_buf = NULL;
	obj->efile.obj_buf_sz = 0;
143 144 145 146 147 148 149 150 151 152 153 154
}

static int bpf_object__elf_init(struct bpf_object *obj)
{
	int err = 0;
	GElf_Ehdr *ep;

	if (obj_elf_valid(obj)) {
		pr_warning("elf init: internal error\n");
		return -EEXIST;
	}

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
	if (obj->efile.obj_buf_sz > 0) {
		/*
		 * obj_buf should have been validated by
		 * bpf_object__open_buffer().
		 */
		obj->efile.elf = elf_memory(obj->efile.obj_buf,
					    obj->efile.obj_buf_sz);
	} else {
		obj->efile.fd = open(obj->path, O_RDONLY);
		if (obj->efile.fd < 0) {
			pr_warning("failed to open %s: %s\n", obj->path,
					strerror(errno));
			return -errno;
		}

		obj->efile.elf = elf_begin(obj->efile.fd,
				LIBBPF_ELF_C_READ_MMAP,
				NULL);
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
	}

	if (!obj->efile.elf) {
		pr_warning("failed to open %s as ELF file\n",
				obj->path);
		err = -EINVAL;
		goto errout;
	}

	if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) {
		pr_warning("failed to get EHDR from %s\n",
				obj->path);
		err = -EINVAL;
		goto errout;
	}
	ep = &obj->efile.ehdr;

	if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
		pr_warning("%s is not an eBPF object file\n",
			obj->path);
		err = -EINVAL;
		goto errout;
	}

	return 0;
errout:
	bpf_object__elf_finish(obj);
	return err;
}

203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
static int
bpf_object__check_endianness(struct bpf_object *obj)
{
	static unsigned int const endian = 1;

	switch (obj->efile.ehdr.e_ident[EI_DATA]) {
	case ELFDATA2LSB:
		/* We are big endian, BPF obj is little endian. */
		if (*(unsigned char const *)&endian != 1)
			goto mismatch;
		break;

	case ELFDATA2MSB:
		/* We are little endian, BPF obj is big endian. */
		if (*(unsigned char const *)&endian != 0)
			goto mismatch;
		break;
	default:
		return -EINVAL;
	}

	return 0;

mismatch:
	pr_warning("Error: endianness mismatch.\n");
	return -EINVAL;
}

231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
static int
bpf_object__init_license(struct bpf_object *obj,
			 void *data, size_t size)
{
	memcpy(obj->license, data,
	       min(size, sizeof(obj->license) - 1));
	pr_debug("license of %s is %s\n", obj->path, obj->license);
	return 0;
}

static int
bpf_object__init_kversion(struct bpf_object *obj,
			  void *data, size_t size)
{
	u32 kver;

	if (size != sizeof(kver)) {
		pr_warning("invalid kver section in %s\n", obj->path);
		return -EINVAL;
	}
	memcpy(&kver, data, sizeof(kver));
	obj->kern_version = kver;
	pr_debug("kernel version of %s is %x\n", obj->path,
		 obj->kern_version);
	return 0;
}

258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
static int
bpf_object__init_maps(struct bpf_object *obj, void *data,
		      size_t size)
{
	if (size == 0) {
		pr_debug("%s doesn't need map definition\n",
			 obj->path);
		return 0;
	}

	obj->maps_buf = malloc(size);
	if (!obj->maps_buf) {
		pr_warning("malloc maps failed: %s\n", obj->path);
		return -ENOMEM;
	}

	obj->maps_buf_sz = size;
	memcpy(obj->maps_buf, data, size);
	pr_debug("maps in %s: %ld bytes\n", obj->path, (long)size);
	return 0;
}

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
static int bpf_object__elf_collect(struct bpf_object *obj)
{
	Elf *elf = obj->efile.elf;
	GElf_Ehdr *ep = &obj->efile.ehdr;
	Elf_Scn *scn = NULL;
	int idx = 0, err = 0;

	/* Elf is corrupted/truncated, avoid calling elf_strptr. */
	if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
		pr_warning("failed to get e_shstrndx from %s\n",
			   obj->path);
		return -EINVAL;
	}

	while ((scn = elf_nextscn(elf, scn)) != NULL) {
		char *name;
		GElf_Shdr sh;
		Elf_Data *data;

		idx++;
		if (gelf_getshdr(scn, &sh) != &sh) {
			pr_warning("failed to get section header from %s\n",
				   obj->path);
			err = -EINVAL;
			goto out;
		}

		name = elf_strptr(elf, ep->e_shstrndx, sh.sh_name);
		if (!name) {
			pr_warning("failed to get section name from %s\n",
				   obj->path);
			err = -EINVAL;
			goto out;
		}

		data = elf_getdata(scn, 0);
		if (!data) {
			pr_warning("failed to get section data from %s(%s)\n",
				   name, obj->path);
			err = -EINVAL;
			goto out;
		}
		pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n",
			 name, (unsigned long)data->d_size,
			 (int)sh.sh_link, (unsigned long)sh.sh_flags,
			 (int)sh.sh_type);
326 327 328 329 330 331 332 333 334

		if (strcmp(name, "license") == 0)
			err = bpf_object__init_license(obj,
						       data->d_buf,
						       data->d_size);
		else if (strcmp(name, "version") == 0)
			err = bpf_object__init_kversion(obj,
							data->d_buf,
							data->d_size);
335 336 337
		else if (strcmp(name, "maps") == 0)
			err = bpf_object__init_maps(obj, data->d_buf,
						    data->d_size);
338 339 340 341 342 343 344 345
		else if (sh.sh_type == SHT_SYMTAB) {
			if (obj->efile.symbols) {
				pr_warning("bpf: multiple SYMTAB in %s\n",
					   obj->path);
				err = -EEXIST;
			} else
				obj->efile.symbols = data;
		}
346 347
		if (err)
			goto out;
348 349 350 351 352
	}
out:
	return err;
}

353 354 355 356 357 358 359 360 361 362
static int bpf_object__validate(struct bpf_object *obj)
{
	if (obj->kern_version == 0) {
		pr_warning("%s doesn't provide kernel version\n",
			   obj->path);
		return -EINVAL;
	}
	return 0;
}

363
static struct bpf_object *
364
__bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz)
365 366 367 368 369 370 371 372
{
	struct bpf_object *obj;

	if (elf_version(EV_CURRENT) == EV_NONE) {
		pr_warning("failed to init libelf for %s\n", path);
		return NULL;
	}

373
	obj = bpf_object__new(path, obj_buf, obj_buf_sz);
374 375 376 377 378
	if (!obj)
		return NULL;

	if (bpf_object__elf_init(obj))
		goto out;
379 380
	if (bpf_object__check_endianness(obj))
		goto out;
381 382
	if (bpf_object__elf_collect(obj))
		goto out;
383 384
	if (bpf_object__validate(obj))
		goto out;
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400

	bpf_object__elf_finish(obj);
	return obj;
out:
	bpf_object__close(obj);
	return NULL;
}

struct bpf_object *bpf_object__open(const char *path)
{
	/* param validation */
	if (!path)
		return NULL;

	pr_debug("loading %s\n", path);

401 402 403 404 405 406 407 408 409 410 411 412 413
	return __bpf_object__open(path, NULL, 0);
}

struct bpf_object *bpf_object__open_buffer(void *obj_buf,
					   size_t obj_buf_sz)
{
	/* param validation */
	if (!obj_buf || obj_buf_sz <= 0)
		return NULL;

	pr_debug("loading object from buffer\n");

	return __bpf_object__open("[buffer]", obj_buf, obj_buf_sz);
414 415 416 417 418 419 420 421 422
}

void bpf_object__close(struct bpf_object *obj)
{
	if (!obj)
		return;

	bpf_object__elf_finish(obj);

423
	zfree(&obj->maps_buf);
424 425
	free(obj);
}