Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9fa3b473 authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'change-libbpf-print-api'

Yonghong Song says:

====================
These are patches responding to my comments for
Magnus's patch (https://patchwork.ozlabs.org/patch/1032848/

).
The goal is to make pr_* macros available to other C files
than libbpf.c, and to simplify API function libbpf_set_print().

Specifically, Patch #1 used global functions
to facilitate pr_* macros in the header files so they
are available in different C files.
Patch #2 removes the global function libbpf_print_level_available()
which is added in Patch 1.
Patch #3 simplified libbpf_set_print() which takes only one print
function with a debug level argument among others.

Changelogs:
 v3 -> v4:
   . rename libbpf internal header util.h to libbpf_util.h
   . rename libbpf internal function libbpf_debug_print() to libbpf_print()
 v2 -> v3:
   . bailed out earlier in libbpf_debug_print() if __libbpf_pr is NULL
   . added missing LIBBPF_DEBUG level check in libbpf.c __base_pr().
 v1 -> v2:
   . Renamed global function libbpf_dprint() to libbpf_debug_print()
     to be more expressive.
   . Removed libbpf_dprint_level_available() as it is used only
     once in btf.c and we can remove it by optimizing for common cases.
====================

Acked-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents cc733578 6f1ae8b6
Loading
Loading
Loading
Loading
+53 −57
Original line number Diff line number Diff line
@@ -9,8 +9,9 @@
#include <linux/btf.h>
#include "btf.h"
#include "bpf.h"
#include "libbpf.h"
#include "libbpf_util.h"

#define elog(fmt, ...) { if (err_log) err_log(fmt, ##__VA_ARGS__); }
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))

@@ -107,54 +108,54 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)
	return 0;
}

static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log)
static int btf_parse_hdr(struct btf *btf)
{
	const struct btf_header *hdr = btf->hdr;
	__u32 meta_left;

	if (btf->data_size < sizeof(struct btf_header)) {
		elog("BTF header not found\n");
		pr_debug("BTF header not found\n");
		return -EINVAL;
	}

	if (hdr->magic != BTF_MAGIC) {
		elog("Invalid BTF magic:%x\n", hdr->magic);
		pr_debug("Invalid BTF magic:%x\n", hdr->magic);
		return -EINVAL;
	}

	if (hdr->version != BTF_VERSION) {
		elog("Unsupported BTF version:%u\n", hdr->version);
		pr_debug("Unsupported BTF version:%u\n", hdr->version);
		return -ENOTSUP;
	}

	if (hdr->flags) {
		elog("Unsupported BTF flags:%x\n", hdr->flags);
		pr_debug("Unsupported BTF flags:%x\n", hdr->flags);
		return -ENOTSUP;
	}

	meta_left = btf->data_size - sizeof(*hdr);
	if (!meta_left) {
		elog("BTF has no data\n");
		pr_debug("BTF has no data\n");
		return -EINVAL;
	}

	if (meta_left < hdr->type_off) {
		elog("Invalid BTF type section offset:%u\n", hdr->type_off);
		pr_debug("Invalid BTF type section offset:%u\n", hdr->type_off);
		return -EINVAL;
	}

	if (meta_left < hdr->str_off) {
		elog("Invalid BTF string section offset:%u\n", hdr->str_off);
		pr_debug("Invalid BTF string section offset:%u\n", hdr->str_off);
		return -EINVAL;
	}

	if (hdr->type_off >= hdr->str_off) {
		elog("BTF type section offset >= string section offset. No type?\n");
		pr_debug("BTF type section offset >= string section offset. No type?\n");
		return -EINVAL;
	}

	if (hdr->type_off & 0x02) {
		elog("BTF type section is not aligned to 4 bytes\n");
		pr_debug("BTF type section is not aligned to 4 bytes\n");
		return -EINVAL;
	}

@@ -163,7 +164,7 @@ static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log)
	return 0;
}

static int btf_parse_str_sec(struct btf *btf, btf_print_fn_t err_log)
static int btf_parse_str_sec(struct btf *btf)
{
	const struct btf_header *hdr = btf->hdr;
	const char *start = btf->nohdr_data + hdr->str_off;
@@ -171,7 +172,7 @@ static int btf_parse_str_sec(struct btf *btf, btf_print_fn_t err_log)

	if (!hdr->str_len || hdr->str_len - 1 > BTF_MAX_NAME_OFFSET ||
	    start[0] || end[-1]) {
		elog("Invalid BTF string section\n");
		pr_debug("Invalid BTF string section\n");
		return -EINVAL;
	}

@@ -180,7 +181,7 @@ static int btf_parse_str_sec(struct btf *btf, btf_print_fn_t err_log)
	return 0;
}

static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
static int btf_parse_type_sec(struct btf *btf)
{
	struct btf_header *hdr = btf->hdr;
	void *nohdr_data = btf->nohdr_data;
@@ -219,7 +220,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
		case BTF_KIND_RESTRICT:
			break;
		default:
			elog("Unsupported BTF_KIND:%u\n",
			pr_debug("Unsupported BTF_KIND:%u\n",
			     BTF_INFO_KIND(t->info));
			return -EINVAL;
		}
@@ -363,7 +364,7 @@ void btf__free(struct btf *btf)
	free(btf);
}

struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
struct btf *btf__new(__u8 *data, __u32 size)
{
	__u32 log_buf_size = 0;
	char *log_buf = NULL;
@@ -376,15 +377,14 @@ struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)

	btf->fd = -1;

	if (err_log) {
	log_buf = malloc(BPF_LOG_BUF_SIZE);
	if (!log_buf) {
		err = -ENOMEM;
		goto done;
	}

	*log_buf = 0;
	log_buf_size = BPF_LOG_BUF_SIZE;
	}

	btf->data = malloc(size);
	if (!btf->data) {
@@ -400,21 +400,21 @@ struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)

	if (btf->fd == -1) {
		err = -errno;
		elog("Error loading BTF: %s(%d)\n", strerror(errno), errno);
		pr_warning("Error loading BTF: %s(%d)\n", strerror(errno), errno);
		if (log_buf && *log_buf)
			elog("%s\n", log_buf);
			pr_warning("%s\n", log_buf);
		goto done;
	}

	err = btf_parse_hdr(btf, err_log);
	err = btf_parse_hdr(btf);
	if (err)
		goto done;

	err = btf_parse_str_sec(btf, err_log);
	err = btf_parse_str_sec(btf);
	if (err)
		goto done;

	err = btf_parse_type_sec(btf, err_log);
	err = btf_parse_type_sec(btf);

done:
	free(log_buf);
@@ -491,7 +491,7 @@ int btf__get_from_id(__u32 id, struct btf **btf)
		goto exit_free;
	}

	*btf = btf__new((__u8 *)(long)btf_info.btf, btf_info.btf_size, NULL);
	*btf = btf__new((__u8 *)(long)btf_info.btf, btf_info.btf_size);
	if (IS_ERR(*btf)) {
		err = PTR_ERR(*btf);
		*btf = NULL;
@@ -514,8 +514,7 @@ struct btf_ext_sec_copy_param {

static int btf_ext_copy_info(struct btf_ext *btf_ext,
			     __u8 *data, __u32 data_size,
			     struct btf_ext_sec_copy_param *ext_sec,
			     btf_print_fn_t err_log)
			     struct btf_ext_sec_copy_param *ext_sec)
{
	const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
	const struct btf_ext_info_sec *sinfo;
@@ -529,14 +528,14 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
	data_size -= hdr->hdr_len;

	if (ext_sec->off & 0x03) {
		elog(".BTF.ext %s section is not aligned to 4 bytes\n",
		pr_debug(".BTF.ext %s section is not aligned to 4 bytes\n",
		     ext_sec->desc);
		return -EINVAL;
	}

	if (data_size < ext_sec->off ||
	    ext_sec->len > data_size - ext_sec->off) {
		elog("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n",
		pr_debug("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n",
		     ext_sec->desc, ext_sec->off, ext_sec->len);
		return -EINVAL;
	}
@@ -546,7 +545,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,

	/* At least a record size */
	if (info_left < sizeof(__u32)) {
		elog(".BTF.ext %s record size not found\n", ext_sec->desc);
		pr_debug(".BTF.ext %s record size not found\n", ext_sec->desc);
		return -EINVAL;
	}

@@ -554,7 +553,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
	record_size = *(__u32 *)info;
	if (record_size < ext_sec->min_rec_size ||
	    record_size & 0x03) {
		elog("%s section in .BTF.ext has invalid record size %u\n",
		pr_debug("%s section in .BTF.ext has invalid record size %u\n",
		     ext_sec->desc, record_size);
		return -EINVAL;
	}
@@ -564,7 +563,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,

	/* If no records, return failure now so .BTF.ext won't be used. */
	if (!info_left) {
		elog("%s section in .BTF.ext has no records", ext_sec->desc);
		pr_debug("%s section in .BTF.ext has no records", ext_sec->desc);
		return -EINVAL;
	}

@@ -574,14 +573,14 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
		__u32 num_records;

		if (info_left < sec_hdrlen) {
			elog("%s section header is not found in .BTF.ext\n",
			pr_debug("%s section header is not found in .BTF.ext\n",
			     ext_sec->desc);
			return -EINVAL;
		}

		num_records = sinfo->num_info;
		if (num_records == 0) {
			elog("%s section has incorrect num_records in .BTF.ext\n",
			pr_debug("%s section has incorrect num_records in .BTF.ext\n",
			     ext_sec->desc);
			return -EINVAL;
		}
@@ -589,7 +588,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
		total_record_size = sec_hdrlen +
				    (__u64)num_records * record_size;
		if (info_left < total_record_size) {
			elog("%s section has incorrect num_records in .BTF.ext\n",
			pr_debug("%s section has incorrect num_records in .BTF.ext\n",
			     ext_sec->desc);
			return -EINVAL;
		}
@@ -610,8 +609,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
}

static int btf_ext_copy_func_info(struct btf_ext *btf_ext,
				  __u8 *data, __u32 data_size,
				  btf_print_fn_t err_log)
				  __u8 *data, __u32 data_size)
{
	const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
	struct btf_ext_sec_copy_param param = {
@@ -622,12 +620,11 @@ static int btf_ext_copy_func_info(struct btf_ext *btf_ext,
		.desc = "func_info"
	};

	return btf_ext_copy_info(btf_ext, data, data_size, &param, err_log);
	return btf_ext_copy_info(btf_ext, data, data_size, &param);
}

static int btf_ext_copy_line_info(struct btf_ext *btf_ext,
				  __u8 *data, __u32 data_size,
				  btf_print_fn_t err_log)
				  __u8 *data, __u32 data_size)
{
	const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
	struct btf_ext_sec_copy_param param = {
@@ -638,37 +635,36 @@ static int btf_ext_copy_line_info(struct btf_ext *btf_ext,
		.desc = "line_info",
	};

	return btf_ext_copy_info(btf_ext, data, data_size, &param, err_log);
	return btf_ext_copy_info(btf_ext, data, data_size, &param);
}

static int btf_ext_parse_hdr(__u8 *data, __u32 data_size,
			     btf_print_fn_t err_log)
static int btf_ext_parse_hdr(__u8 *data, __u32 data_size)
{
	const struct btf_ext_header *hdr = (struct btf_ext_header *)data;

	if (data_size < offsetof(struct btf_ext_header, func_info_off) ||
	    data_size < hdr->hdr_len) {
		elog("BTF.ext header not found");
		pr_debug("BTF.ext header not found");
		return -EINVAL;
	}

	if (hdr->magic != BTF_MAGIC) {
		elog("Invalid BTF.ext magic:%x\n", hdr->magic);
		pr_debug("Invalid BTF.ext magic:%x\n", hdr->magic);
		return -EINVAL;
	}

	if (hdr->version != BTF_VERSION) {
		elog("Unsupported BTF.ext version:%u\n", hdr->version);
		pr_debug("Unsupported BTF.ext version:%u\n", hdr->version);
		return -ENOTSUP;
	}

	if (hdr->flags) {
		elog("Unsupported BTF.ext flags:%x\n", hdr->flags);
		pr_debug("Unsupported BTF.ext flags:%x\n", hdr->flags);
		return -ENOTSUP;
	}

	if (data_size == hdr->hdr_len) {
		elog("BTF.ext has no data\n");
		pr_debug("BTF.ext has no data\n");
		return -EINVAL;
	}

@@ -685,12 +681,12 @@ void btf_ext__free(struct btf_ext *btf_ext)
	free(btf_ext);
}

struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
struct btf_ext *btf_ext__new(__u8 *data, __u32 size)
{
	struct btf_ext *btf_ext;
	int err;

	err = btf_ext_parse_hdr(data, size, err_log);
	err = btf_ext_parse_hdr(data, size);
	if (err)
		return ERR_PTR(err);

@@ -698,13 +694,13 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
	if (!btf_ext)
		return ERR_PTR(-ENOMEM);

	err = btf_ext_copy_func_info(btf_ext, data, size, err_log);
	err = btf_ext_copy_func_info(btf_ext, data, size);
	if (err) {
		btf_ext__free(btf_ext);
		return ERR_PTR(err);
	}

	err = btf_ext_copy_line_info(btf_ext, data, size, err_log);
	err = btf_ext_copy_line_info(btf_ext, data, size);
	if (err) {
		btf_ext__free(btf_ext);
		return ERR_PTR(err);
+2 −5
Original line number Diff line number Diff line
@@ -55,11 +55,8 @@ struct btf_ext_header {
	__u32	line_info_len;
};

typedef int (*btf_print_fn_t)(const char *, ...)
	__attribute__((format(printf, 1, 2)));

LIBBPF_API void btf__free(struct btf *btf);
LIBBPF_API struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
LIBBPF_API struct btf *btf__new(__u8 *data, __u32 size);
LIBBPF_API __s32 btf__find_by_name(const struct btf *btf,
				   const char *type_name);
LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
@@ -70,7 +67,7 @@ LIBBPF_API int btf__fd(const struct btf *btf);
LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
LIBBPF_API int btf__get_from_id(__u32 id, struct btf **btf);

struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
struct btf_ext *btf_ext__new(__u8 *data, __u32 size);
void btf_ext__free(struct btf_ext *btf_ext);
int btf_ext__reloc_func_info(const struct btf *btf,
			     const struct btf_ext *btf_ext,
+23 −24
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include "bpf.h"
#include "btf.h"
#include "str_error.h"
#include "libbpf_util.h"

#ifndef EM_BPF
#define EM_BPF 247
@@ -53,39 +54,39 @@

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

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

	if (level == LIBBPF_DEBUG)
		return 0;

	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)
static __printf(2, 3) libbpf_print_fn_t __libbpf_pr = __base_pr;

#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 fn)
{
	__libbpf_pr = fn;
}

void libbpf_set_print(libbpf_print_fn_t warn,
		      libbpf_print_fn_t info,
		      libbpf_print_fn_t debug)
__printf(2, 3)
void libbpf_print(enum libbpf_print_level level, const char *format, ...)
{
	__pr_warning = warn;
	__pr_info = info;
	__pr_debug = debug;
	va_list args;

	if (!__libbpf_pr)
		return;

	va_start(args, format);
	__libbpf_pr(level, format, args);
	va_end(args);
}

#define STRERR_BUFSIZE  128
@@ -839,8 +840,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
		else if (strcmp(name, "maps") == 0)
			obj->efile.maps_shndx = idx;
		else if (strcmp(name, BTF_ELF_SEC) == 0) {
			obj->btf = btf__new(data->d_buf, data->d_size,
					    __pr_debug);
			obj->btf = btf__new(data->d_buf, data->d_size);
			if (IS_ERR(obj->btf)) {
				pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
					   BTF_ELF_SEC, PTR_ERR(obj->btf));
@@ -915,8 +915,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
				 BTF_EXT_ELF_SEC, BTF_ELF_SEC);
		} else {
			obj->btf_ext = btf_ext__new(btf_ext_data->d_buf,
						    btf_ext_data->d_size,
						    __pr_debug);
						    btf_ext_data->d_size);
			if (IS_ERR(obj->btf_ext)) {
				pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
					   BTF_EXT_ELF_SEC,
+10 −10
Original line number Diff line number Diff line
@@ -47,17 +47,17 @@ enum libbpf_errno {

LIBBPF_API int libbpf_strerror(int err, char *buf, size_t size);

/*
 * __printf is defined in include/linux/compiler-gcc.h. However,
 * it would be better if libbpf.h didn't depend on Linux header files.
 * So instead of __printf, here we use gcc attribute directly.
 */
typedef int (*libbpf_print_fn_t)(const char *, ...)
	__attribute__((format(printf, 1, 2)));
enum libbpf_print_level {
        LIBBPF_WARN,
        LIBBPF_INFO,
        LIBBPF_DEBUG,
};

typedef int (*libbpf_print_fn_t)(enum libbpf_print_level level,
				 const char *, ...)
	__attribute__((format(printf, 2, 3)));

LIBBPF_API void libbpf_set_print(libbpf_print_fn_t warn,
				 libbpf_print_fn_t info,
				 libbpf_print_fn_t debug);
LIBBPF_API void libbpf_set_print(libbpf_print_fn_t fn);

/* Hide internal to user */
struct bpf_object;
+30 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2019 Facebook */

#ifndef __LIBBPF_LIBBPF_UTIL_H
#define __LIBBPF_LIBBPF_UTIL_H

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

extern void libbpf_print(enum libbpf_print_level level,
			 const char *format, ...)
	__attribute__((format(printf, 2, 3)));

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

#define pr_warning(fmt, ...)	__pr(LIBBPF_WARN, fmt, ##__VA_ARGS__)
#define pr_info(fmt, ...)	__pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
#define pr_debug(fmt, ...)	__pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif
Loading