btf_encoder: run BTF deduplication before writing out to ELF
After btf_encoder completes DWARF to BTF 0-to-1 conversion, utilize libbpf to construct struct btf and run btf__dedup() algorithm on it. This significantly reduces number of BTF types and strings section size without losing any information. Committer testing: Before: $ cp ../build/v5.0-rc3+/vmlinux . $ ls -la vmlinux -rwxrwxr-x. 1 acme acme 654357792 Feb 18 10:51 vmlinux $ pahole -J vmlinux $ ls -la vmlinux -rwxrwxr-x. 1 acme acme 824950072 Feb 18 10:52 vmlinux $ echo $((824950072 - 654357792)) 170592280 $ $ readelf -SW vmlinux | head -4 There are 79 section headers, starting at offset 0x312ba978: Section Headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al <SNIP> [78] .BTF PROGBITS 0000000000000000 27053da9 a266bcd 00 0 0 1 $ >>> 0xa266bcd 170290125 After: $ cp ../build/v5.0-rc3+/vmlinux . $ ls -la vmlinux -rwxrwxr-x. 1 acme acme 654357792 Feb 18 11:01 vmlinux $ pahole -J vmlinux $ ls -la vmlinux -rwxrwxr-x. 1 acme acme 656641544 Feb 18 11:01 vmlinux $ echo $((656641544 - 654357792)) 2283752 $ readelf -SW vmlinux | grep BTF [78] .BTF PROGBITS 0000000000000000 27053da9 1e3c9e 00 0 0 1 >>> 0x1e3c9e 1981598 >>> Signed-off-by: Andrii Nakryiko <andriin@fb.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexei Starovoitov <ast@fb.com> Cc: bpf@vger.kernel.org Cc: dwarves@vger.kernel.org Cc: kernel-team@fb.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
54106025cd
commit
dd3a7d3ab3
42
libbtf.c
42
libbtf.c
|
@ -17,6 +17,9 @@
|
|||
|
||||
#include "libbtf.h"
|
||||
#include "lib/bpf/include/uapi/linux/btf.h"
|
||||
#include "lib/bpf/include/linux/err.h"
|
||||
#include "lib/bpf/src/btf.h"
|
||||
#include "lib/bpf/src/libbpf.h"
|
||||
#include "dutil.h"
|
||||
#include "gobuffer.h"
|
||||
#include "dwarves.h"
|
||||
|
@ -566,19 +569,21 @@ int32_t btf_elf__add_func_proto(struct btf_elf *btfe, struct ftype *ftype, uint3
|
|||
return type_id;
|
||||
}
|
||||
|
||||
static int btf_elf__write(struct btf_elf *btfe)
|
||||
static int btf_elf__write(const char *filename, struct btf *btf)
|
||||
{
|
||||
GElf_Shdr shdr_mem, *shdr;
|
||||
GElf_Ehdr ehdr_mem, *ehdr;
|
||||
Elf_Data *btf_elf = NULL;
|
||||
Elf_Scn *scn = NULL;
|
||||
Elf *elf = NULL;
|
||||
const void *btf_data;
|
||||
uint32_t btf_size;
|
||||
int fd, err = -1;
|
||||
size_t strndx;
|
||||
|
||||
fd = open(btfe->filename, O_RDWR);
|
||||
fd = open(filename, O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Cannot open %s\n", btfe->filename);
|
||||
fprintf(stderr, "Cannot open %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -617,10 +622,12 @@ static int btf_elf__write(struct btf_elf *btfe)
|
|||
}
|
||||
}
|
||||
|
||||
btf_data = btf__get_raw_data(btf, &btf_size);
|
||||
|
||||
if (btf_elf) {
|
||||
/* Exisiting .BTF section found */
|
||||
btf_elf->d_buf = btfe->data;
|
||||
btf_elf->d_size = btfe->size;
|
||||
btf_elf->d_buf = (void *)btf_data;
|
||||
btf_elf->d_size = btf_size;
|
||||
elf_flagdata(btf_elf, ELF_C_SET, ELF_F_DIRTY);
|
||||
|
||||
if (elf_update(elf, ELF_C_NULL) >= 0 &&
|
||||
|
@ -646,10 +653,9 @@ static int btf_elf__write(struct btf_elf *btfe)
|
|||
}
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "%s --add-section .BTF=%s %s",
|
||||
llvm_objcopy, tmp_fn, btfe->filename);
|
||||
llvm_objcopy, tmp_fn, filename);
|
||||
|
||||
if (write(fd, btfe->data, btfe->size) == btfe->size &&
|
||||
!system(cmd))
|
||||
if (write(fd, btf_data, btf_size) == btf_size && !system(cmd))
|
||||
err = 0;
|
||||
|
||||
unlink(tmp_fn);
|
||||
|
@ -663,9 +669,15 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int libbpf_log(enum libbpf_print_level level, const char *format, va_list args)
|
||||
{
|
||||
return vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
int btf_elf__encode(struct btf_elf *btfe, uint8_t flags)
|
||||
{
|
||||
struct btf_header *hdr;
|
||||
struct btf *btf;
|
||||
|
||||
/* Empty file, nothing to do, so... done! */
|
||||
if (gobuffer__size(&btfe->types) == 0)
|
||||
|
@ -695,5 +707,17 @@ int btf_elf__encode(struct btf_elf *btfe, uint8_t flags)
|
|||
|
||||
*(char *)(btf_elf__nohdr_data(btfe) + hdr->str_off) = '\0';
|
||||
|
||||
return btf_elf__write(btfe);
|
||||
libbpf_set_print(libbpf_log);
|
||||
|
||||
btf = btf__new(btfe->data, btfe->size);
|
||||
if (IS_ERR(btf)) {
|
||||
fprintf(stderr, "%s: btf__new failed!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (btf__dedup(btf, NULL, NULL)) {
|
||||
fprintf(stderr, "%s: btf__dedup failed!", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return btf_elf__write(btfe->filename, btf);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue