diff options
| author | Wang Nan <wangnan0@huawei.com> | 2015-06-30 22:13:57 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-08-07 09:16:57 -0400 |
| commit | cb1e5e961991ee9b2cbfd3bf06ef490ea578cd2f (patch) | |
| tree | ca588da8a349ded2f2cf7d1b310124b84df2ae44 /tools/lib | |
| parent | 296036653ae8b1367ec9d06d65377c2e2371b153 (diff) | |
bpf tools: Collect version and license from ELF sections
Expand bpf_obj_elf_collect() to collect license and kernel version
information in eBPF object file. eBPF object file should have a section
named 'license', which contains a string. It should also have a section
named 'version', contains a u32 LINUX_VERSION_CODE.
bpf_obj_validate() is introduced to validate object file after loaded.
Currently it only check existence of 'version' section.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1435716878-189507-10-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/lib')
| -rw-r--r-- | tools/lib/bpf/libbpf.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index d8d6eb580188..95c8d8e5c350 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <fcntl.h> | 14 | #include <fcntl.h> |
| 15 | #include <errno.h> | 15 | #include <errno.h> |
| 16 | #include <asm/unistd.h> | 16 | #include <asm/unistd.h> |
| 17 | #include <linux/kernel.h> | ||
| 17 | #include <linux/bpf.h> | 18 | #include <linux/bpf.h> |
| 18 | #include <libelf.h> | 19 | #include <libelf.h> |
| 19 | #include <gelf.h> | 20 | #include <gelf.h> |
| @@ -78,6 +79,8 @@ void libbpf_set_print(libbpf_print_fn_t warn, | |||
| 78 | #endif | 79 | #endif |
| 79 | 80 | ||
| 80 | struct bpf_object { | 81 | struct bpf_object { |
| 82 | char license[64]; | ||
| 83 | u32 kern_version; | ||
| 81 | /* | 84 | /* |
| 82 | * Information when doing elf related work. Only valid if fd | 85 | * Information when doing elf related work. Only valid if fd |
| 83 | * is valid. | 86 | * is valid. |
| @@ -220,6 +223,33 @@ mismatch: | |||
| 220 | return -EINVAL; | 223 | return -EINVAL; |
| 221 | } | 224 | } |
| 222 | 225 | ||
| 226 | static int | ||
| 227 | bpf_object__init_license(struct bpf_object *obj, | ||
| 228 | void *data, size_t size) | ||
| 229 | { | ||
| 230 | memcpy(obj->license, data, | ||
| 231 | min(size, sizeof(obj->license) - 1)); | ||
| 232 | pr_debug("license of %s is %s\n", obj->path, obj->license); | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | static int | ||
| 237 | bpf_object__init_kversion(struct bpf_object *obj, | ||
| 238 | void *data, size_t size) | ||
| 239 | { | ||
| 240 | u32 kver; | ||
| 241 | |||
| 242 | if (size != sizeof(kver)) { | ||
| 243 | pr_warning("invalid kver section in %s\n", obj->path); | ||
| 244 | return -EINVAL; | ||
| 245 | } | ||
| 246 | memcpy(&kver, data, sizeof(kver)); | ||
| 247 | obj->kern_version = kver; | ||
| 248 | pr_debug("kernel version of %s is %x\n", obj->path, | ||
| 249 | obj->kern_version); | ||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | |||
| 223 | static int bpf_object__elf_collect(struct bpf_object *obj) | 253 | static int bpf_object__elf_collect(struct bpf_object *obj) |
| 224 | { | 254 | { |
| 225 | Elf *elf = obj->efile.elf; | 255 | Elf *elf = obj->efile.elf; |
| @@ -266,11 +296,32 @@ static int bpf_object__elf_collect(struct bpf_object *obj) | |||
| 266 | name, (unsigned long)data->d_size, | 296 | name, (unsigned long)data->d_size, |
| 267 | (int)sh.sh_link, (unsigned long)sh.sh_flags, | 297 | (int)sh.sh_link, (unsigned long)sh.sh_flags, |
| 268 | (int)sh.sh_type); | 298 | (int)sh.sh_type); |
| 299 | |||
| 300 | if (strcmp(name, "license") == 0) | ||
| 301 | err = bpf_object__init_license(obj, | ||
| 302 | data->d_buf, | ||
| 303 | data->d_size); | ||
| 304 | else if (strcmp(name, "version") == 0) | ||
| 305 | err = bpf_object__init_kversion(obj, | ||
| 306 | data->d_buf, | ||
| 307 | data->d_size); | ||
| 308 | if (err) | ||
| 309 | goto out; | ||
| 269 | } | 310 | } |
| 270 | out: | 311 | out: |
| 271 | return err; | 312 | return err; |
| 272 | } | 313 | } |
| 273 | 314 | ||
| 315 | static int bpf_object__validate(struct bpf_object *obj) | ||
| 316 | { | ||
| 317 | if (obj->kern_version == 0) { | ||
| 318 | pr_warning("%s doesn't provide kernel version\n", | ||
| 319 | obj->path); | ||
| 320 | return -EINVAL; | ||
| 321 | } | ||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 274 | static struct bpf_object * | 325 | static struct bpf_object * |
| 275 | __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz) | 326 | __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz) |
| 276 | { | 327 | { |
| @@ -291,6 +342,8 @@ __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz) | |||
| 291 | goto out; | 342 | goto out; |
| 292 | if (bpf_object__elf_collect(obj)) | 343 | if (bpf_object__elf_collect(obj)) |
| 293 | goto out; | 344 | goto out; |
| 345 | if (bpf_object__validate(obj)) | ||
| 346 | goto out; | ||
| 294 | 347 | ||
| 295 | bpf_object__elf_finish(obj); | 348 | bpf_object__elf_finish(obj); |
| 296 | return obj; | 349 | return obj; |
