Blame SOURCES/0001-btf-Remove-ftrace-filter.patch

0e5b81
From 58a98f76ac95b1bb11920ff2b58206b2364e6b3b Mon Sep 17 00:00:00 2001
0e5b81
From: Martin KaFai Lau <kafai@fb.com>
0e5b81
Date: Thu, 6 May 2021 13:56:22 -0700
0e5b81
Subject: [PATCH] btf: Remove ftrace filter
0e5b81
0e5b81
BTF is currently generated for functions that are in ftrace list
0e5b81
or extern.
0e5b81
0e5b81
A recent use case also needs BTF generated for functions included in
0e5b81
allowlist.
0e5b81
0e5b81
In particular, the kernel commit:
0e5b81
0e5b81
  e78aea8b2170 ("bpf: tcp: Put some tcp cong functions in allowlist for bpf-tcp-cc")
0e5b81
0e5b81
allows bpf program to directly call a few tcp cc kernel functions. Those
0e5b81
kernel functions are currently allowed only if CONFIG_DYNAMIC_FTRACE
0e5b81
is set to ensure they are in the ftrace list but this kconfig dependency
0e5b81
is unnecessary.
0e5b81
0e5b81
Those kernel functions are specified under an ELF section .BTF_ids.
0e5b81
There was an earlier attempt [0] to add another filter for the functions in
0e5b81
the .BTF_ids section.  That discussion concluded that the ftrace filter
0e5b81
should be removed instead.
0e5b81
0e5b81
This patch is to remove the ftrace filter and its related functions.
0e5b81
0e5b81
Number of BTF FUNC with and without is_ftrace_func():
0e5b81
My kconfig in x86: 40643 vs 46225
0e5b81
Jiri reported on arm: 25022 vs 55812
0e5b81
0e5b81
[0]: https://lore.kernel.org/dwarves/20210423213728.3538141-1-kafai@fb.com/
0e5b81
0e5b81
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
0e5b81
Tested-by: Nathan Chancellor <nathan@kernel.org> # build
0e5b81
Acked-by: Jiri Olsa <jolsa@kernel.org>
0e5b81
Acked-by: Jiri Slaby <jirislaby@kernel.org>
0e5b81
Cc: Andrii Nakryiko <andrii@kernel.org>
0e5b81
Cc: Jiri Olsa <jolsa@kernel.org>
0e5b81
Cc: kernel-team@fb.com
0e5b81
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
0e5b81
---
0e5b81
 btf_encoder.c | 285 ++------------------------------------------------
0e5b81
 1 file changed, 7 insertions(+), 278 deletions(-)
0e5b81
0e5b81
diff --git a/btf_encoder.c b/btf_encoder.c
0e5b81
index 80e896961d4e..c711f124b31e 100644
0e5b81
--- a/btf_encoder.c
0e5b81
+++ b/btf_encoder.c
0e5b81
@@ -27,17 +27,8 @@
0e5b81
  */
0e5b81
 #define KSYM_NAME_LEN 128
0e5b81
 
0e5b81
-struct funcs_layout {
0e5b81
-	unsigned long mcount_start;
0e5b81
-	unsigned long mcount_stop;
0e5b81
-	unsigned long mcount_sec_idx;
0e5b81
-};
0e5b81
-
0e5b81
 struct elf_function {
0e5b81
 	const char	*name;
0e5b81
-	unsigned long	 addr;
0e5b81
-	unsigned long	 size;
0e5b81
-	unsigned long	 sh_addr;
0e5b81
 	bool		 generated;
0e5b81
 };
0e5b81
 
0e5b81
@@ -64,12 +55,9 @@ static void delete_functions(void)
0e5b81
 #define max(x, y) ((x) < (y) ? (y) : (x))
0e5b81
 #endif
0e5b81
 
0e5b81
-static int collect_function(struct btf_elf *btfe, GElf_Sym *sym,
0e5b81
-			    size_t sym_sec_idx)
0e5b81
+static int collect_function(struct btf_elf *btfe, GElf_Sym *sym)
0e5b81
 {
0e5b81
 	struct elf_function *new;
0e5b81
-	static GElf_Shdr sh;
0e5b81
-	static size_t last_idx;
0e5b81
 	const char *name;
0e5b81
 
0e5b81
 	if (elf_sym__type(sym) != STT_FUNC)
0e5b81
@@ -91,257 +79,12 @@ static int collect_function(struct btf_elf *btfe, GElf_Sym *sym,
0e5b81
 		functions = new;
0e5b81
 	}
0e5b81
 
0e5b81
-	if (sym_sec_idx != last_idx) {
0e5b81
-		if (!elf_section_by_idx(btfe->elf, &sh, sym_sec_idx))
0e5b81
-			return 0;
0e5b81
-		last_idx = sym_sec_idx;
0e5b81
-	}
0e5b81
-
0e5b81
 	functions[functions_cnt].name = name;
0e5b81
-	functions[functions_cnt].addr = elf_sym__value(sym);
0e5b81
-	functions[functions_cnt].size = elf_sym__size(sym);
0e5b81
-	functions[functions_cnt].sh_addr = sh.sh_addr;
0e5b81
 	functions[functions_cnt].generated = false;
0e5b81
 	functions_cnt++;
0e5b81
 	return 0;
0e5b81
 }
0e5b81
 
0e5b81
-static int addrs_cmp(const void *_a, const void *_b)
0e5b81
-{
0e5b81
-	const __u64 *a = _a;
0e5b81
-	const __u64 *b = _b;
0e5b81
-
0e5b81
-	if (*a == *b)
0e5b81
-		return 0;
0e5b81
-	return *a < *b ? -1 : 1;
0e5b81
-}
0e5b81
-
0e5b81
-static int get_vmlinux_addrs(struct btf_elf *btfe, struct funcs_layout *fl,
0e5b81
-			     __u64 **paddrs, __u64 *pcount)
0e5b81
-{
0e5b81
-	__u64 *addrs, count, offset;
0e5b81
-	unsigned int addr_size, i;
0e5b81
-	Elf_Data *data;
0e5b81
-	GElf_Shdr shdr;
0e5b81
-	Elf_Scn *sec;
0e5b81
-
0e5b81
-	/* Initialize for the sake of all error paths below. */
0e5b81
-	*paddrs = NULL;
0e5b81
-	*pcount = 0;
0e5b81
-
0e5b81
-	if (!fl->mcount_start || !fl->mcount_stop)
0e5b81
-		return 0;
0e5b81
-
0e5b81
-	/*
0e5b81
-	 * Find mcount addressed marked by __start_mcount_loc
0e5b81
-	 * and __stop_mcount_loc symbols and load them into
0e5b81
-	 * sorted array.
0e5b81
-	 */
0e5b81
-	sec = elf_getscn(btfe->elf, fl->mcount_sec_idx);
0e5b81
-	if (!sec || !gelf_getshdr(sec, &shdr)) {
0e5b81
-		fprintf(stderr, "Failed to get section(%lu) header.\n",
0e5b81
-			fl->mcount_sec_idx);
0e5b81
-		return -1;
0e5b81
-	}
0e5b81
-
0e5b81
-	/* Get address size from processed file's ELF class. */
0e5b81
-	addr_size = gelf_getclass(btfe->elf) == ELFCLASS32 ? 4 : 8;
0e5b81
-
0e5b81
-	offset = fl->mcount_start - shdr.sh_addr;
0e5b81
-	count  = (fl->mcount_stop - fl->mcount_start) / addr_size;
0e5b81
-
0e5b81
-	data = elf_getdata(sec, 0);
0e5b81
-	if (!data) {
0e5b81
-		fprintf(stderr, "Failed to get section(%lu) data.\n",
0e5b81
-			fl->mcount_sec_idx);
0e5b81
-		return -1;
0e5b81
-	}
0e5b81
-
0e5b81
-	addrs = malloc(count * sizeof(addrs[0]));
0e5b81
-	if (!addrs) {
0e5b81
-		fprintf(stderr, "Failed to allocate memory for ftrace addresses.\n");
0e5b81
-		return -1;
0e5b81
-	}
0e5b81
-
0e5b81
-	if (addr_size == sizeof(__u64)) {
0e5b81
-		memcpy(addrs, data->d_buf + offset, count * addr_size);
0e5b81
-	} else {
0e5b81
-		for (i = 0; i < count; i++)
0e5b81
-			addrs[i] = (__u64) *((__u32 *) (data->d_buf + offset + i * addr_size));
0e5b81
-	}
0e5b81
-
0e5b81
-	*paddrs = addrs;
0e5b81
-	*pcount = count;
0e5b81
-	return 0;
0e5b81
-}
0e5b81
-
0e5b81
-static int
0e5b81
-get_kmod_addrs(struct btf_elf *btfe, __u64 **paddrs, __u64 *pcount)
0e5b81
-{
0e5b81
-	__u64 *addrs, count;
0e5b81
-	unsigned int addr_size, i;
0e5b81
-	GElf_Shdr shdr_mcount;
0e5b81
-	Elf_Data *data;
0e5b81
-	Elf_Scn *sec;
0e5b81
-
0e5b81
-	/* Initialize for the sake of all error paths below. */
0e5b81
-	*paddrs = NULL;
0e5b81
-	*pcount = 0;
0e5b81
-
0e5b81
-	/* get __mcount_loc */
0e5b81
-	sec = elf_section_by_name(btfe->elf, &btfe->ehdr, &shdr_mcount,
0e5b81
-				  "__mcount_loc", NULL);
0e5b81
-	if (!sec) {
0e5b81
-		if (btf_elf__verbose) {
0e5b81
-			printf("%s: '%s' doesn't have __mcount_loc section\n", __func__,
0e5b81
-			       btfe->filename);
0e5b81
-		}
0e5b81
-		return 0;
0e5b81
-	}
0e5b81
-
0e5b81
-	data = elf_getdata(sec, NULL);
0e5b81
-	if (!data) {
0e5b81
-		fprintf(stderr, "Failed to data for __mcount_loc section.\n");
0e5b81
-		return -1;
0e5b81
-	}
0e5b81
-
0e5b81
-	/* Get address size from processed file's ELF class. */
0e5b81
-	addr_size = gelf_getclass(btfe->elf) == ELFCLASS32 ? 4 : 8;
0e5b81
-
0e5b81
-	count = data->d_size / addr_size;
0e5b81
-
0e5b81
-	addrs = malloc(count * sizeof(addrs[0]));
0e5b81
-	if (!addrs) {
0e5b81
-		fprintf(stderr, "Failed to allocate memory for ftrace addresses.\n");
0e5b81
-		return -1;
0e5b81
-	}
0e5b81
-
0e5b81
-	if (addr_size == sizeof(__u64)) {
0e5b81
-		memcpy(addrs, data->d_buf, count * addr_size);
0e5b81
-	} else {
0e5b81
-		for (i = 0; i < count; i++)
0e5b81
-			addrs[i] = (__u64) *((__u32 *) (data->d_buf + i * addr_size));
0e5b81
-	}
0e5b81
-
0e5b81
-	/*
0e5b81
-	 * We get Elf object from dwfl_module_getelf function,
0e5b81
-	 * which performs all possible relocations, including
0e5b81
-	 * __mcount_loc section.
0e5b81
-	 *
0e5b81
-	 * So addrs array now contains relocated values, which
0e5b81
-	 * we need take into account when we compare them to
0e5b81
-	 * functions values, see comment in setup_functions
0e5b81
-	 * function.
0e5b81
-	 */
0e5b81
-	*paddrs = addrs;
0e5b81
-	*pcount = count;
0e5b81
-	return 0;
0e5b81
-}
0e5b81
-
0e5b81
-static int is_ftrace_func(struct elf_function *func, __u64 *addrs, __u64 count)
0e5b81
-{
0e5b81
-	__u64 start = func->addr;
0e5b81
-	__u64 addr, end = func->addr + func->size;
0e5b81
-
0e5b81
-	/*
0e5b81
-	 * The invariant here is addr[r] that is the smallest address
0e5b81
-	 * that is >= than function start addr. Except the corner case
0e5b81
-	 * where there is no such r, but for that we have a final check
0e5b81
-	 * in the return.
0e5b81
-	 */
0e5b81
-	size_t l = 0, r = count - 1, m;
0e5b81
-
0e5b81
-	/* make sure we don't use invalid r */
0e5b81
-	if (count == 0)
0e5b81
-		return false;
0e5b81
-
0e5b81
-	while (l < r) {
0e5b81
-		m = l + (r - l) / 2;
0e5b81
-		addr = addrs[m];
0e5b81
-
0e5b81
-		if (addr >= start) {
0e5b81
-			/* we satisfy invariant, so tighten r */
0e5b81
-			r = m;
0e5b81
-		} else {
0e5b81
-			/* m is not good enough as l, maybe m + 1 will be */
0e5b81
-			l = m + 1;
0e5b81
-		}
0e5b81
-	}
0e5b81
-
0e5b81
-	return start <= addrs[r] && addrs[r] < end;
0e5b81
-}
0e5b81
-
0e5b81
-static int setup_functions(struct btf_elf *btfe, struct funcs_layout *fl)
0e5b81
-{
0e5b81
-	__u64 *addrs, count, i;
0e5b81
-	int functions_valid = 0;
0e5b81
-	bool kmod = false;
0e5b81
-
0e5b81
-	/*
0e5b81
-	 * Check if we are processing vmlinux image and
0e5b81
-	 * get mcount data if it's detected.
0e5b81
-	 */
0e5b81
-	if (get_vmlinux_addrs(btfe, fl, &addrs, &count))
0e5b81
-		return -1;
0e5b81
-
0e5b81
-	/*
0e5b81
-	 * Check if we are processing kernel module and
0e5b81
-	 * get mcount data if it's detected.
0e5b81
-	 */
0e5b81
-	if (!addrs) {
0e5b81
-		if (get_kmod_addrs(btfe, &addrs, &count))
0e5b81
-			return -1;
0e5b81
-		kmod = true;
0e5b81
-	}
0e5b81
-
0e5b81
-	if (!addrs) {
0e5b81
-		if (btf_elf__verbose)
0e5b81
-			printf("ftrace symbols not detected, falling back to DWARF data\n");
0e5b81
-		delete_functions();
0e5b81
-		return 0;
0e5b81
-	}
0e5b81
-
0e5b81
-	qsort(addrs, count, sizeof(addrs[0]), addrs_cmp);
0e5b81
-	qsort(functions, functions_cnt, sizeof(functions[0]), functions_cmp);
0e5b81
-
0e5b81
-	/*
0e5b81
-	 * Let's got through all collected functions and filter
0e5b81
-	 * out those that are not in ftrace.
0e5b81
-	 */
0e5b81
-	for (i = 0; i < functions_cnt; i++) {
0e5b81
-		struct elf_function *func = &functions[i];
0e5b81
-		/*
0e5b81
-		 * For vmlinux image both addrs[x] and functions[x]::addr
0e5b81
-		 * values are final address and are comparable.
0e5b81
-		 *
0e5b81
-		 * For kernel module addrs[x] is final address, but
0e5b81
-		 * functions[x]::addr is relative address within section
0e5b81
-		 * and needs to be relocated by adding sh_addr.
0e5b81
-		 */
0e5b81
-		if (kmod)
0e5b81
-			func->addr += func->sh_addr;
0e5b81
-
0e5b81
-		/* Make sure function is within ftrace addresses. */
0e5b81
-		if (is_ftrace_func(func, addrs, count)) {
0e5b81
-			/*
0e5b81
-			 * We iterate over sorted array, so we can easily skip
0e5b81
-			 * not valid item and move following valid field into
0e5b81
-			 * its place, and still keep the 'new' array sorted.
0e5b81
-			 */
0e5b81
-			if (i != functions_valid)
0e5b81
-				functions[functions_valid] = functions[i];
0e5b81
-			functions_valid++;
0e5b81
-		}
0e5b81
-	}
0e5b81
-
0e5b81
-	functions_cnt = functions_valid;
0e5b81
-	free(addrs);
0e5b81
-
0e5b81
-	if (btf_elf__verbose)
0e5b81
-		printf("Found %d functions!\n", functions_cnt);
0e5b81
-	return 0;
0e5b81
-}
0e5b81
-
0e5b81
 static struct elf_function *find_function(const struct btf_elf *btfe,
0e5b81
 					  const char *name)
0e5b81
 {
0e5b81
@@ -620,23 +363,8 @@ static int collect_percpu_var(struct btf_elf *btfe, GElf_Sym *sym,
0e5b81
 	return 0;
0e5b81
 }
0e5b81
 
0e5b81
-static void collect_symbol(GElf_Sym *sym, struct funcs_layout *fl,
0e5b81
-			   size_t sym_sec_idx)
0e5b81
-{
0e5b81
-	if (!fl->mcount_start &&
0e5b81
-	    !strcmp("__start_mcount_loc", elf_sym__name(sym, btfe->symtab))) {
0e5b81
-		fl->mcount_start = sym->st_value;
0e5b81
-		fl->mcount_sec_idx = sym_sec_idx;
0e5b81
-	}
0e5b81
-
0e5b81
-	if (!fl->mcount_stop &&
0e5b81
-	    !strcmp("__stop_mcount_loc", elf_sym__name(sym, btfe->symtab)))
0e5b81
-		fl->mcount_stop = sym->st_value;
0e5b81
-}
0e5b81
-
0e5b81
 static int collect_symbols(struct btf_elf *btfe, bool collect_percpu_vars)
0e5b81
 {
0e5b81
-	struct funcs_layout fl = { };
0e5b81
 	Elf32_Word sym_sec_idx;
0e5b81
 	uint32_t core_id;
0e5b81
 	GElf_Sym sym;
0e5b81
@@ -648,9 +376,8 @@ static int collect_symbols(struct btf_elf *btfe, bool collect_percpu_vars)
0e5b81
 	elf_symtab__for_each_symbol_index(btfe->symtab, core_id, sym, sym_sec_idx) {
0e5b81
 		if (collect_percpu_vars && collect_percpu_var(btfe, &sym, sym_sec_idx))
0e5b81
 			return -1;
0e5b81
-		if (collect_function(btfe, &sym, sym_sec_idx))
0e5b81
+		if (collect_function(btfe, &sym))
0e5b81
 			return -1;
0e5b81
-		collect_symbol(&sym, &fl, sym_sec_idx);
0e5b81
 	}
0e5b81
 
0e5b81
 	if (collect_percpu_vars) {
0e5b81
@@ -661,9 +388,11 @@ static int collect_symbols(struct btf_elf *btfe, bool collect_percpu_vars)
0e5b81
 			printf("Found %d per-CPU variables!\n", percpu_var_cnt);
0e5b81
 	}
0e5b81
 
0e5b81
-	if (functions_cnt && setup_functions(btfe, &fl)) {
0e5b81
-		fprintf(stderr, "Failed to filter DWARF functions\n");
0e5b81
-		return -1;
0e5b81
+	if (functions_cnt) {
0e5b81
+		qsort(functions, functions_cnt, sizeof(functions[0]),
0e5b81
+		      functions_cmp);
0e5b81
+		if (btf_elf__verbose)
0e5b81
+			printf("Found %d functions!\n", functions_cnt);
0e5b81
 	}
0e5b81
 
0e5b81
 	return 0;
0e5b81
-- 
0e5b81
2.31.1
0e5b81