diff options
Diffstat (limited to 'tools/lib/bpf/btf.c')
| -rw-r--r-- | tools/lib/bpf/btf.c | 127 | 
1 files changed, 87 insertions, 40 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index bfef3d606b54..4843e44916f7 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -386,10 +386,10 @@ __s32 btf__find_by_name_kind(const struct btf *btf, const char *type_name,  void btf__free(struct btf *btf)  { -	if (!btf) +	if (IS_ERR_OR_NULL(btf))  		return; -	if (btf->fd != -1) +	if (btf->fd >= 0)  		close(btf->fd);  	free(btf->data); @@ -397,7 +397,7 @@ void btf__free(struct btf *btf)  	free(btf);  } -struct btf *btf__new(__u8 *data, __u32 size) +struct btf *btf__new(const void *data, __u32 size)  {  	struct btf *btf;  	int err; @@ -562,6 +562,83 @@ done:  	return btf;  } +struct btf *btf__parse_raw(const char *path) +{ +	struct btf *btf = NULL; +	void *data = NULL; +	FILE *f = NULL; +	__u16 magic; +	int err = 0; +	long sz; + +	f = fopen(path, "rb"); +	if (!f) { +		err = -errno; +		goto err_out; +	} + +	/* check BTF magic */ +	if (fread(&magic, 1, sizeof(magic), f) < sizeof(magic)) { +		err = -EIO; +		goto err_out; +	} +	if (magic != BTF_MAGIC) { +		/* definitely not a raw BTF */ +		err = -EPROTO; +		goto err_out; +	} + +	/* get file size */ +	if (fseek(f, 0, SEEK_END)) { +		err = -errno; +		goto err_out; +	} +	sz = ftell(f); +	if (sz < 0) { +		err = -errno; +		goto err_out; +	} +	/* rewind to the start */ +	if (fseek(f, 0, SEEK_SET)) { +		err = -errno; +		goto err_out; +	} + +	/* pre-alloc memory and read all of BTF data */ +	data = malloc(sz); +	if (!data) { +		err = -ENOMEM; +		goto err_out; +	} +	if (fread(data, 1, sz, f) < sz) { +		err = -EIO; +		goto err_out; +	} + +	/* finally parse BTF data */ +	btf = btf__new(data, sz); + +err_out: +	free(data); +	if (f) +		fclose(f); +	return err ? ERR_PTR(err) : btf; +} + +struct btf *btf__parse(const char *path, struct btf_ext **btf_ext) +{ +	struct btf *btf; + +	if (btf_ext) +		*btf_ext = NULL; + +	btf = btf__parse_raw(path); +	if (!IS_ERR(btf) || PTR_ERR(btf) != -EPROTO) +		return btf; + +	return btf__parse_elf(path, btf_ext); +} +  static int compare_vsi_off(const void *_a, const void *_b)  {  	const struct btf_var_secinfo *a = _a; @@ -700,6 +777,11 @@ int btf__fd(const struct btf *btf)  	return btf->fd;  } +void btf__set_fd(struct btf *btf, int fd) +{ +	btf->fd = fd; +} +  const void *btf__get_raw_data(const struct btf *btf, __u32 *size)  {  	*size = btf->data_size; @@ -1020,7 +1102,7 @@ static int btf_ext_parse_hdr(__u8 *data, __u32 data_size)  void btf_ext__free(struct btf_ext *btf_ext)  { -	if (!btf_ext) +	if (IS_ERR_OR_NULL(btf_ext))  		return;  	free(btf_ext->data);  	free(btf_ext); @@ -2946,41 +3028,6 @@ static int btf_dedup_remap_types(struct btf_dedup *d)  	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. @@ -3016,7 +3063,7 @@ struct btf *libbpf_find_kernel_btf(void)  			continue;  		if (locations[i].raw_btf) -			btf = btf_load_raw(path); +			btf = btf__parse_raw(path);  		else  			btf = btf__parse_elf(path, NULL);  | 
