Merge branch 'bpf-libbpf-read-sysfs-btf'
Andrii Nakryiko says: ==================== Now that kernel's BTF is exposed through sysfs at well-known location, attempt to load it first as a target BTF for the purpose of BPF CO-RE relocations. Patch #1 is a follow-up patch to rename /sys/kernel/btf/kernel into /sys/kernel/btf/vmlinux. Patch #2 adds ability to load raw BTF contents from sysfs and expands the list of locations libbpf attempts to load vmlinux BTF from. ==================== Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
		
						commit
						72ef80b5ee
					
				| @ -6,7 +6,7 @@ Description: | ||||
| 		Contains BTF type information and related data for kernel and | ||||
| 		kernel modules. | ||||
| 
 | ||||
| What:		/sys/kernel/btf/kernel | ||||
| What:		/sys/kernel/btf/vmlinux | ||||
| Date:		Aug 2019 | ||||
| KernelVersion:	5.5 | ||||
| Contact:	bpf@vger.kernel.org | ||||
|  | ||||
| @ -9,30 +9,30 @@ | ||||
| #include <linux/sysfs.h> | ||||
| 
 | ||||
| /* See scripts/link-vmlinux.sh, gen_btf() func for details */ | ||||
| extern char __weak _binary__btf_kernel_bin_start[]; | ||||
| extern char __weak _binary__btf_kernel_bin_end[]; | ||||
| extern char __weak _binary__btf_vmlinux_bin_start[]; | ||||
| extern char __weak _binary__btf_vmlinux_bin_end[]; | ||||
| 
 | ||||
| static ssize_t | ||||
| btf_kernel_read(struct file *file, struct kobject *kobj, | ||||
| 		struct bin_attribute *bin_attr, | ||||
| 		char *buf, loff_t off, size_t len) | ||||
| btf_vmlinux_read(struct file *file, struct kobject *kobj, | ||||
| 		 struct bin_attribute *bin_attr, | ||||
| 		 char *buf, loff_t off, size_t len) | ||||
| { | ||||
| 	memcpy(buf, _binary__btf_kernel_bin_start + off, len); | ||||
| 	memcpy(buf, _binary__btf_vmlinux_bin_start + off, len); | ||||
| 	return len; | ||||
| } | ||||
| 
 | ||||
| static struct bin_attribute bin_attr_btf_kernel __ro_after_init = { | ||||
| 	.attr = { .name = "kernel", .mode = 0444, }, | ||||
| 	.read = btf_kernel_read, | ||||
| static struct bin_attribute bin_attr_btf_vmlinux __ro_after_init = { | ||||
| 	.attr = { .name = "vmlinux", .mode = 0444, }, | ||||
| 	.read = btf_vmlinux_read, | ||||
| }; | ||||
| 
 | ||||
| static struct kobject *btf_kobj; | ||||
| 
 | ||||
| static int __init btf_kernel_init(void) | ||||
| static int __init btf_vmlinux_init(void) | ||||
| { | ||||
| 	int err; | ||||
| 
 | ||||
| 	if (!_binary__btf_kernel_bin_start) | ||||
| 	if (!_binary__btf_vmlinux_bin_start) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	btf_kobj = kobject_create_and_add("btf", kernel_kobj); | ||||
| @ -42,10 +42,10 @@ static int __init btf_kernel_init(void) | ||||
| 		return err; | ||||
| 	} | ||||
| 
 | ||||
| 	bin_attr_btf_kernel.size = _binary__btf_kernel_bin_end - | ||||
| 				   _binary__btf_kernel_bin_start; | ||||
| 	bin_attr_btf_vmlinux.size = _binary__btf_vmlinux_bin_end - | ||||
| 				    _binary__btf_vmlinux_bin_start; | ||||
| 
 | ||||
| 	return sysfs_create_bin_file(btf_kobj, &bin_attr_btf_kernel); | ||||
| 	return sysfs_create_bin_file(btf_kobj, &bin_attr_btf_vmlinux); | ||||
| } | ||||
| 
 | ||||
| subsys_initcall(btf_kernel_init); | ||||
| subsys_initcall(btf_vmlinux_init); | ||||
|  | ||||
| @ -117,9 +117,9 @@ gen_btf() | ||||
| 	# dump .BTF section into raw binary file to link with final vmlinux | ||||
| 	bin_arch=$(${OBJDUMP} -f ${1} | grep architecture | \ | ||||
| 		cut -d, -f1 | cut -d' ' -f2) | ||||
| 	${OBJCOPY} --dump-section .BTF=.btf.kernel.bin ${1} 2>/dev/null | ||||
| 	${OBJCOPY} --dump-section .BTF=.btf.vmlinux.bin ${1} 2>/dev/null | ||||
| 	${OBJCOPY} -I binary -O ${CONFIG_OUTPUT_FORMAT} -B ${bin_arch} \ | ||||
| 		--rename-section .data=.BTF .btf.kernel.bin ${2} | ||||
| 		--rename-section .data=.BTF .btf.vmlinux.bin ${2} | ||||
| } | ||||
| 
 | ||||
| # Create ${2} .o file with all symbols from the ${1} object file | ||||
| @ -227,10 +227,10 @@ ${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o | ||||
| info MODINFO modules.builtin.modinfo | ||||
| ${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo | ||||
| 
 | ||||
| btf_kernel_bin_o="" | ||||
| btf_vmlinux_bin_o="" | ||||
| if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then | ||||
| 	if gen_btf .tmp_vmlinux.btf .btf.kernel.bin.o ; then | ||||
| 		btf_kernel_bin_o=.btf.kernel.bin.o | ||||
| 	if gen_btf .tmp_vmlinux.btf .btf.vmlinux.bin.o ; then | ||||
| 		btf_vmlinux_bin_o=.btf.vmlinux.bin.o | ||||
| 	fi | ||||
| fi | ||||
| 
 | ||||
| @ -265,11 +265,11 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then | ||||
| 	kallsyms_vmlinux=.tmp_vmlinux2 | ||||
| 
 | ||||
| 	# step 1 | ||||
| 	vmlinux_link .tmp_vmlinux1 ${btf_kernel_bin_o} | ||||
| 	vmlinux_link .tmp_vmlinux1 ${btf_vmlinux_bin_o} | ||||
| 	kallsyms .tmp_vmlinux1 .tmp_kallsyms1.o | ||||
| 
 | ||||
| 	# step 2 | ||||
| 	vmlinux_link .tmp_vmlinux2 .tmp_kallsyms1.o ${btf_kernel_bin_o} | ||||
| 	vmlinux_link .tmp_vmlinux2 .tmp_kallsyms1.o ${btf_vmlinux_bin_o} | ||||
| 	kallsyms .tmp_vmlinux2 .tmp_kallsyms2.o | ||||
| 
 | ||||
| 	# step 3 | ||||
| @ -280,13 +280,13 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then | ||||
| 		kallsymso=.tmp_kallsyms3.o | ||||
| 		kallsyms_vmlinux=.tmp_vmlinux3 | ||||
| 
 | ||||
| 		vmlinux_link .tmp_vmlinux3 .tmp_kallsyms2.o ${btf_kernel_bin_o} | ||||
| 		vmlinux_link .tmp_vmlinux3 .tmp_kallsyms2.o ${btf_vmlinux_bin_o} | ||||
| 		kallsyms .tmp_vmlinux3 .tmp_kallsyms3.o | ||||
| 	fi | ||||
| fi | ||||
| 
 | ||||
| info LD vmlinux | ||||
| vmlinux_link vmlinux "${kallsymso}" "${btf_kernel_bin_o}" | ||||
| vmlinux_link vmlinux "${kallsymso}" "${btf_vmlinux_bin_o}" | ||||
| 
 | ||||
| if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then | ||||
| 	info SORTEX vmlinux | ||||
|  | ||||
| @ -2807,15 +2807,61 @@ static int bpf_core_reloc_insn(struct bpf_program *prog, int insn_off, | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static struct btf *btf_load_raw(const char *path) | ||||
| { | ||||
| 	struct btf *btf; | ||||
| 	size_t read_cnt; | ||||
| 	struct stat st; | ||||
| 	void *data; | ||||
| 	FILE *f; | ||||
| 
 | ||||
| 	if (stat(path, &st)) | ||||
| 		return ERR_PTR(-errno); | ||||
| 
 | ||||
| 	data = malloc(st.st_size); | ||||
| 	if (!data) | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 
 | ||||
| 	f = fopen(path, "rb"); | ||||
| 	if (!f) { | ||||
| 		btf = ERR_PTR(-errno); | ||||
| 		goto cleanup; | ||||
| 	} | ||||
| 
 | ||||
| 	read_cnt = fread(data, 1, st.st_size, f); | ||||
| 	fclose(f); | ||||
| 	if (read_cnt < st.st_size) { | ||||
| 		btf = ERR_PTR(-EBADF); | ||||
| 		goto cleanup; | ||||
| 	} | ||||
| 
 | ||||
| 	btf = btf__new(data, read_cnt); | ||||
| 
 | ||||
| cleanup: | ||||
| 	free(data); | ||||
| 	return btf; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Probe few well-known locations for vmlinux kernel image and try to load BTF | ||||
|  * data out of it to use for target BTF. | ||||
|  */ | ||||
| static struct btf *bpf_core_find_kernel_btf(void) | ||||
| { | ||||
| 	const char *locations[] = { | ||||
| 		"/lib/modules/%1$s/vmlinux-%1$s", | ||||
| 		"/usr/lib/modules/%1$s/kernel/vmlinux", | ||||
| 	struct { | ||||
| 		const char *path_fmt; | ||||
| 		bool raw_btf; | ||||
| 	} locations[] = { | ||||
| 		/* try canonical vmlinux BTF through sysfs first */ | ||||
| 		{ "/sys/kernel/btf/vmlinux", true /* raw BTF */ }, | ||||
| 		/* fall back to trying to find vmlinux ELF on disk otherwise */ | ||||
| 		{ "/boot/vmlinux-%1$s" }, | ||||
| 		{ "/lib/modules/%1$s/vmlinux-%1$s" }, | ||||
| 		{ "/lib/modules/%1$s/build/vmlinux" }, | ||||
| 		{ "/usr/lib/modules/%1$s/kernel/vmlinux" }, | ||||
| 		{ "/usr/lib/debug/boot/vmlinux-%1$s" }, | ||||
| 		{ "/usr/lib/debug/boot/vmlinux-%1$s.debug" }, | ||||
| 		{ "/usr/lib/debug/lib/modules/%1$s/vmlinux" }, | ||||
| 	}; | ||||
| 	char path[PATH_MAX + 1]; | ||||
| 	struct utsname buf; | ||||
| @ -2825,14 +2871,18 @@ static struct btf *bpf_core_find_kernel_btf(void) | ||||
| 	uname(&buf); | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(locations); i++) { | ||||
| 		snprintf(path, PATH_MAX, locations[i], buf.release); | ||||
| 		snprintf(path, PATH_MAX, locations[i].path_fmt, buf.release); | ||||
| 
 | ||||
| 		if (access(path, R_OK)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		btf = btf__parse_elf(path, NULL); | ||||
| 		pr_debug("kernel BTF load from '%s': %ld\n", | ||||
| 			 path, PTR_ERR(btf)); | ||||
| 		if (locations[i].raw_btf) | ||||
| 			btf = btf_load_raw(path); | ||||
| 		else | ||||
| 			btf = btf__parse_elf(path, NULL); | ||||
| 
 | ||||
| 		pr_debug("loading kernel BTF '%s': %ld\n", | ||||
| 			 path, IS_ERR(btf) ? PTR_ERR(btf) : 0); | ||||
| 		if (IS_ERR(btf)) | ||||
| 			continue; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user