From: Giuliano Procida <gprocida@google.com>
To: dwarves@vger.kernel.org
Cc: acme@kernel.org, andrii@kernel.org, ast@kernel.org,
gprocida@google.com, maennich@google.com,
kernel-team@android.com, kernel-team@fb.com, bpf@vger.kernel.org
Subject: [PATCH dwarves 2/4] btf_encoder: Add .BTF section using libelf
Date: Mon, 25 Jan 2021 13:06:23 +0000 [thread overview]
Message-ID: <20210125130625.2030186-3-gprocida@google.com> (raw)
In-Reply-To: <20210125130625.2030186-1-gprocida@google.com>
pahole -J uses libelf directly when updating a .BTF section. However,
it uses llvm-objcopy to add .BTF sections. This commit switches to
using libelf for both cases.
This eliminates pahole's dependency on llvm-objcopy. One unfortunate
side-effect is that vmlinux actually increases in size. It seems that
llvm-objcopy modifies the .strtab section, discarding many strings. I
speculate that is it discarding strings not referenced from .symtab
and updating the references therein.
In this initial version layout is left completely up to libelf which
may be OK for non-loadable object files, but is probably no good for
things like vmlinux where all the offsets may change. This is
addressed in a follow-up commit.
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
libbtf.c | 145 ++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 100 insertions(+), 45 deletions(-)
diff --git a/libbtf.c b/libbtf.c
index 9f76283..fb8e043 100644
--- a/libbtf.c
+++ b/libbtf.c
@@ -699,6 +699,7 @@ static int btf_elf__write(const char *filename, struct btf *btf)
uint32_t raw_btf_size;
int fd, err = -1;
size_t strndx;
+ void *str_table = NULL;
fd = open(filename, O_RDWR);
if (fd < 0) {
@@ -741,74 +742,128 @@ static int btf_elf__write(const char *filename, struct btf *btf)
}
/*
- * First we look if there was already a .BTF section to overwrite.
+ * First we check if there is already a .BTF section present.
*/
-
elf_getshdrstrndx(elf, &strndx);
+ Elf_Scn *btf_scn = 0;
while ((scn = elf_nextscn(elf, scn)) != NULL) {
shdr = gelf_getshdr(scn, &shdr_mem);
if (shdr == NULL)
continue;
char *secname = elf_strptr(elf, strndx, shdr->sh_name);
if (strcmp(secname, ".BTF") == 0) {
- btf_data = elf_getdata(scn, btf_data);
+ btf_scn = scn;
break;
}
}
- raw_btf_data = btf__get_raw_data(btf, &raw_btf_size);
-
- if (btf_data) {
- /* Exisiting .BTF section found */
- btf_data->d_buf = (void *)raw_btf_data;
- btf_data->d_size = raw_btf_size;
- elf_flagdata(btf_data, ELF_C_SET, ELF_F_DIRTY);
+ Elf_Scn *str_scn = elf_getscn(elf, strndx);
+ if (!str_scn) {
+ fprintf(stderr, "%s: elf_getscn(strndx) failed\n", __func__);
+ goto out;
+ }
- if (elf_update(elf, ELF_C_NULL) >= 0 &&
- elf_update(elf, ELF_C_WRITE) >= 0)
- err = 0;
- else
- fprintf(stderr, "%s: elf_update failed: %s.\n",
- __func__, elf_errmsg(elf_errno()));
+ size_t dot_btf_offset = 0;
+ if (btf_scn) {
+ /* Existing .BTF section found */
+ btf_data = elf_getdata(btf_scn, NULL);
+ if (!btf_data) {
+ fprintf(stderr, "%s: elf_getdata failed: %s\n", __func__,
+ elf_errmsg(elf_errno()));
+ goto out;
+ }
} else {
- const char *llvm_objcopy;
- char tmp_fn[PATH_MAX];
- char cmd[PATH_MAX * 2];
-
- llvm_objcopy = getenv("LLVM_OBJCOPY");
- if (!llvm_objcopy)
- llvm_objcopy = "llvm-objcopy";
-
- /* Use objcopy to add a .BTF section */
- snprintf(tmp_fn, sizeof(tmp_fn), "%s.btf", filename);
- close(fd);
- fd = creat(tmp_fn, S_IRUSR | S_IWUSR);
- if (fd == -1) {
- fprintf(stderr, "%s: open(%s) failed!\n", __func__,
- tmp_fn);
+ /* Add ".BTF" to the section name string table */
+ Elf_Data *str_data = elf_getdata(str_scn, NULL);
+ if (!str_data) {
+ fprintf(stderr, "%s: elf_getdata(str_scn) failed: %s\n",
+ __func__, elf_errmsg(elf_errno()));
goto out;
}
-
- if (write(fd, raw_btf_data, raw_btf_size) != raw_btf_size) {
- fprintf(stderr, "%s: write of %d bytes to '%s' failed: %d!\n",
- __func__, raw_btf_size, tmp_fn, errno);
- goto unlink;
+ dot_btf_offset = str_data->d_size;
+ size_t new_str_size = dot_btf_offset + 5;
+ str_table = malloc(new_str_size);
+ if (!str_table) {
+ fprintf(stderr, "%s: malloc(%zu) failed: %s\n", __func__,
+ new_str_size, elf_errmsg(elf_errno()));
+ goto out;
}
+ memcpy(str_table, str_data->d_buf, dot_btf_offset);
+ memcpy(str_table + dot_btf_offset, ".BTF", 5);
+ str_data->d_buf = str_table;
+ str_data->d_size = new_str_size;
+ elf_flagdata(str_data, ELF_C_SET, ELF_F_DIRTY);
+
+ /* Create a new section */
+ btf_scn = elf_newscn(elf);
+ if (!btf_scn) {
+ fprintf(stderr, "%s: elf_newscn failed: %s\n",
+ __func__, elf_errmsg(elf_errno()));
+ goto out;
+ }
+ btf_data = elf_newdata(btf_scn);
+ if (!btf_data) {
+ fprintf(stderr, "%s: elf_newdata failed: %s\n",
+ __func__, elf_errmsg(elf_errno()));
+ goto out;
+ }
+ }
- snprintf(cmd, sizeof(cmd), "%s --add-section .BTF=%s %s",
- llvm_objcopy, tmp_fn, filename);
- if (system(cmd)) {
- fprintf(stderr, "%s: failed to add .BTF section to '%s': %d!\n",
- __func__, filename, errno);
- goto unlink;
+ /* (Re)populate the BTF section data */
+ raw_btf_data = btf__get_raw_data(btf, &raw_btf_size);
+ btf_data->d_buf = (void *)raw_btf_data;
+ btf_data->d_size = raw_btf_size;
+ btf_data->d_type = ELF_T_BYTE;
+ btf_data->d_version = EV_CURRENT;
+ elf_flagdata(btf_data, ELF_C_SET, ELF_F_DIRTY);
+
+ /* Update .BTF section in the SHT */
+ GElf_Shdr btf_shdr_mem;
+ GElf_Shdr *btf_shdr = gelf_getshdr(btf_scn, &btf_shdr_mem);
+ if (!btf_shdr) {
+ fprintf(stderr, "%s: elf_getshdr(btf_scn) failed: %s\n",
+ __func__, elf_errmsg(elf_errno()));
+ goto out;
+ }
+ btf_shdr->sh_entsize = 0;
+ btf_shdr->sh_flags = 0;
+ if (dot_btf_offset)
+ btf_shdr->sh_name = dot_btf_offset;
+ btf_shdr->sh_type = SHT_PROGBITS;
+ if (!gelf_update_shdr(btf_scn, btf_shdr)) {
+ fprintf(stderr, "%s: gelf_update_shdr failed: %s\n",
+ __func__, elf_errmsg(elf_errno()));
+ goto out;
+ }
+
+ if (elf_update(elf, ELF_C_NULL) < 0) {
+ fprintf(stderr, "%s: elf_update (layout) failed: %s\n",
+ __func__, elf_errmsg(elf_errno()));
+ goto out;
+ }
+
+ size_t phnum = 0;
+ if (!elf_getphdrnum(elf, &phnum)) {
+ for (size_t ix = 0; ix < phnum; ++ix) {
+ GElf_Phdr phdr;
+ GElf_Phdr *elf_phdr = gelf_getphdr(elf, ix, &phdr);
+ size_t filesz = gelf_fsize(elf, ELF_T_PHDR, 1, EV_CURRENT);
+ fprintf(stderr, "type: %d %d\n", elf_phdr->p_type, PT_PHDR);
+ fprintf(stderr, "offset: %lu %lu\n", elf_phdr->p_offset, ehdr->e_phoff);
+ fprintf(stderr, "filesize: %lu %lu\n", elf_phdr->p_filesz, filesz);
}
+ }
- err = 0;
- unlink:
- unlink(tmp_fn);
+ if (elf_update(elf, ELF_C_WRITE) < 0) {
+ fprintf(stderr, "%s: elf_update (write) failed: %s\n",
+ __func__, elf_errmsg(elf_errno()));
+ goto out;
}
+ err = 0;
out:
+ if (str_table)
+ free(str_table);
if (fd != -1)
close(fd);
if (elf)
--
2.30.0.280.ga3ce27912f-goog
next prev parent reply other threads:[~2021-01-26 19:32 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-25 13:06 [PATCH dwarves 0/4] BTF ELF writing changes Giuliano Procida
2021-01-25 13:06 ` [PATCH dwarves 1/4] btf_encoder: Improve ELF error reporting Giuliano Procida
2021-01-25 13:06 ` Giuliano Procida [this message]
2021-01-27 23:23 ` [PATCH dwarves 2/4] btf_encoder: Add .BTF section using libelf Jiri Olsa
2021-01-28 13:35 ` Giuliano Procida
2021-02-05 13:40 ` Giuliano Procida
2021-01-25 13:06 ` [PATCH dwarves 3/4] btf_encoder: Manually lay out updated ELF sections Giuliano Procida
2021-01-25 13:06 ` [PATCH dwarves 4/4] btf_encoder: Align .BTF section to 8 bytes Giuliano Procida
2021-01-26 19:55 ` [PATCH dwarves 0/4] BTF ELF writing changes Jiri Olsa
2021-01-27 1:10 ` Giuliano Procida
2021-01-27 1:42 ` Arnaldo Carvalho de Melo
2021-01-27 14:06 ` Arnaldo Carvalho de Melo
2021-01-27 14:36 ` Giuliano Procida
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210125130625.2030186-3-gprocida@google.com \
--to=gprocida@google.com \
--cc=acme@kernel.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dwarves@vger.kernel.org \
--cc=kernel-team@android.com \
--cc=kernel-team@fb.com \
--cc=maennich@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox