From patchwork Mon Jan 25 13:06:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 12045489 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 769A7C433E0 for ; Tue, 26 Jan 2021 05:37:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4EAEF2223D for ; Tue, 26 Jan 2021 05:37:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732849AbhAZFgz (ORCPT ); Tue, 26 Jan 2021 00:36:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55348 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728593AbhAYNH6 (ORCPT ); Mon, 25 Jan 2021 08:07:58 -0500 Received: from mail-wr1-x449.google.com (mail-wr1-x449.google.com [IPv6:2a00:1450:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EF63EC061788 for ; Mon, 25 Jan 2021 05:06:38 -0800 (PST) Received: by mail-wr1-x449.google.com with SMTP id w5so7962111wrl.9 for ; Mon, 25 Jan 2021 05:06:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=gPE7b3/M6uCT5ZEUoYFVzS554jwY/Cx+KLicb2SXbs0=; b=qt1z7TkNoS9LG+sx0K0P2/jQ07smZJ2i7rZJ+/ppPnkhnkD/VRRQKBlBnCwbtrmA0V izVEVH/olwD1HuRV7zRoly2WCQ9PDzLXooovKlvr2DsjBImzmVs6Dgk0ppRAFvPZ81vy BuIbhkeZVS4FQK+JG/afbflq4vkYCfyWEZAyMlpbKdn99ljHtMYvLUZflECLPmC+SEhB zX8gKtdkFMBUn5Ihk/H+kpa9DbpGCYKuA5zBnMN9XiFmx0N0gE91H0eEwgJn+Oy9eCbj HzZg3wVHo7jj9FMk4mTYmmLvL+GVPoteCCrqySCQZBwAOyx0DPI0yCl7J1QRF+tWaw5Q XwQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=gPE7b3/M6uCT5ZEUoYFVzS554jwY/Cx+KLicb2SXbs0=; b=PU8MsHqVRjNuCmuvlCmK6u1Mjs3rw2R1jBF2VD/31jkIjKeztbYsT88YQG00Z7/Vo7 PkQDqZux8Q9YccIMAYlQIpUZPtGEMuB7lFJM4QTBN8/dXIHnBup/YoexsUv7YTCEKo2Q RD/CQmiurDaVLrR2KXnPoahKQ6hTsZboBLVDQHbZcawC22LnyQkAYzU/2S9AsrvaHIDG 6SkahDZdMPYXkooV6eIJVnkwEzptsxgyR9DYQXFXl7qI+skeyXdyMoin2p6BQ5Uhlsk7 v08FTrRl/Y+Vap80njJUHxSWbFGH680Z63hl/Ynq1XtXI5zNC3nD/+pc6JzKuUBSlZiB y4tw== X-Gm-Message-State: AOAM533xn+u+bVEfANHsnYcy7lkTqA8WT04AF1C1VOOaw98JiWmxPsLB J4zoJrNc+8+ofn9hnUEPAIDMkJwXEfAhPg== X-Google-Smtp-Source: ABdhPJwqUswTeWhqfYqtt3aXneF0oEqCmZ9xQz2yt3073LrQB25loOFYEchMfmwmuQ6wi3mE576iHo6J2Uyt3w== Sender: "gprocida via sendgmr" X-Received: from tef.lon.corp.google.com ([2a00:79e0:d:110:a6ae:11ff:fe11:4f04]) (user=gprocida job=sendgmr) by 2002:adf:a11d:: with SMTP id o29mr882505wro.45.1611579997395; Mon, 25 Jan 2021 05:06:37 -0800 (PST) Date: Mon, 25 Jan 2021 13:06:22 +0000 In-Reply-To: <20210125130625.2030186-1-gprocida@google.com> Message-Id: <20210125130625.2030186-2-gprocida@google.com> Mime-Version: 1.0 References: <20210125130625.2030186-1-gprocida@google.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog Subject: [PATCH dwarves 1/4] btf_encoder: Improve ELF error reporting From: Giuliano Procida 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 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org libelf provides an errno/strerror-like facility. This commit updates various error messages to include helpful error text. Signed-off-by: Giuliano Procida --- libbtf.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/libbtf.c b/libbtf.c index 7552d8e..9f76283 100644 --- a/libbtf.c +++ b/libbtf.c @@ -110,8 +110,8 @@ try_as_raw_btf: btfe->elf = elf_begin(btfe->in_fd, ELF_C_READ_MMAP, NULL); if (!btfe->elf) { - fprintf(stderr, "%s: cannot read %s ELF file.\n", - __func__, filename); + fprintf(stderr, "%s: cannot read %s ELF file: %s.\n", + __func__, filename, elf_errmsg(elf_errno())); goto errout; } } @@ -707,13 +707,15 @@ static int btf_elf__write(const char *filename, struct btf *btf) } if (elf_version(EV_CURRENT) == EV_NONE) { - fprintf(stderr, "Cannot set libelf version.\n"); + fprintf(stderr, "Cannot set libelf version: %s.\n", + elf_errmsg(elf_errno())); goto out; } elf = elf_begin(fd, ELF_C_RDWR, NULL); if (elf == NULL) { - fprintf(stderr, "Cannot update ELF file.\n"); + fprintf(stderr, "Cannot update ELF file: %s.\n", + elf_errmsg(elf_errno())); goto out; } @@ -721,7 +723,8 @@ static int btf_elf__write(const char *filename, struct btf *btf) ehdr = gelf_getehdr(elf, &ehdr_mem); if (ehdr == NULL) { - fprintf(stderr, "%s: elf_getehdr failed.\n", __func__); + fprintf(stderr, "%s: elf_getehdr failed: %s.\n", __func__, + elf_errmsg(elf_errno())); goto out; } @@ -764,6 +767,9 @@ static int btf_elf__write(const char *filename, struct btf *btf) 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())); } else { const char *llvm_objcopy; char tmp_fn[PATH_MAX]; From patchwork Mon Jan 25 13:06:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 12045493 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B230AC433DB for ; Tue, 26 Jan 2021 05:37:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 887972223D for ; Tue, 26 Jan 2021 05:37:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728591AbhAZFhH (ORCPT ); Tue, 26 Jan 2021 00:37:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55742 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728239AbhAYNJS (ORCPT ); Mon, 25 Jan 2021 08:09:18 -0500 Received: from mail-wm1-x349.google.com (mail-wm1-x349.google.com [IPv6:2a00:1450:4864:20::349]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 30A13C06178A for ; Mon, 25 Jan 2021 05:06:41 -0800 (PST) Received: by mail-wm1-x349.google.com with SMTP id y9so6101107wmi.8 for ; Mon, 25 Jan 2021 05:06:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=F7AnyDl54dMT8pOE1ownSAAEiPW1w7lE/lQbqOo0kHk=; b=gEL1ZGEf6L6I9cex2xnE/t/vNl60tu9KjliGn4SahnLmh6CyGc/Lo+XIX8ZjtSUqeO 1TfQA6qBxqMlBFW2RVP3Po39K+y8a8EvV9LyIjW582NWOYd4fBDtjrHP4IArCiCKpPKG yyQckg3gsbosC0cftj2QNTmGUXHK3KHriyb9LW/0HQGrVPgAfWugDiAFVrHBx/t+fKZO 6vZKxI2/0KWze6DUnm6CzOcgyPHq5XSAQy4FfPOEwN8dkIT5e1G62pUY8ePXmBTKDwOc tpNEVZ7MqCVBd+7NQnDmmP/i7F5lDN6o/NH6Jt7691pwkKbw3/dRXlkuyirw7cg0PSN5 wjGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=F7AnyDl54dMT8pOE1ownSAAEiPW1w7lE/lQbqOo0kHk=; b=j3qWGdY6UYnKHS78SbJCgNmPqc+4K6kDCX2GV/51AYQrgEKGwXI3EWPRQFORQbzFBO 2zOSfejWDfGcKEkTZfTl9mVIlTg+ybZAZ4dpHi/B2kmOpkoDCLkk4/kndsuPzgKWXf/f UrY9zRVjVfpilyu67asK5FXaf5qHBN+iX2ad2lejlXhMg7cmWNae7b8tF+UieCFr4ZHE FTO/oB2+rsGJpro1jXiFsC4CaDQfJzLaWP5xDkpbdeflY3MShpE2POQdCfQ04ppRnxLw rF3lXqo+vNhuwxkEIa+WNhJwXJtFLwELAbWPxsxIhaGLAHkZJZU4bXDUyxHl2DwjwBBu 6WHQ== X-Gm-Message-State: AOAM531qNhxjSvgb/pyNpLNkU8chyLXicRfvIZstno2MeLXPHfu2tbg1 bKG9ezFU/za+B9OCJO//iiI80TAXdR6+gQ== X-Google-Smtp-Source: ABdhPJyjiMlHb58uSEQ07K9Y2g0t6ehfwAR0BVHTzeyY324+46HvLumnWJtqRYMh7IzIGPVXnR8ZPTKoHd9LZA== Sender: "gprocida via sendgmr" X-Received: from tef.lon.corp.google.com ([2a00:79e0:d:110:a6ae:11ff:fe11:4f04]) (user=gprocida job=sendgmr) by 2002:a05:6000:188b:: with SMTP id a11mr848105wri.151.1611579999642; Mon, 25 Jan 2021 05:06:39 -0800 (PST) Date: Mon, 25 Jan 2021 13:06:23 +0000 In-Reply-To: <20210125130625.2030186-1-gprocida@google.com> Message-Id: <20210125130625.2030186-3-gprocida@google.com> Mime-Version: 1.0 References: <20210125130625.2030186-1-gprocida@google.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog Subject: [PATCH dwarves 2/4] btf_encoder: Add .BTF section using libelf From: Giuliano Procida 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 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org 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 --- 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) From patchwork Mon Jan 25 13:06:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 12045495 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0D438C433E0 for ; Tue, 26 Jan 2021 05:37:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DF85F2223D for ; Tue, 26 Jan 2021 05:37:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387908AbhAZFhT (ORCPT ); Tue, 26 Jan 2021 00:37:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55776 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728274AbhAYNJ2 (ORCPT ); Mon, 25 Jan 2021 08:09:28 -0500 Received: from mail-qt1-x84a.google.com (mail-qt1-x84a.google.com [IPv6:2607:f8b0:4864:20::84a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 27904C061793 for ; Mon, 25 Jan 2021 05:06:43 -0800 (PST) Received: by mail-qt1-x84a.google.com with SMTP id z19so7122902qtv.20 for ; Mon, 25 Jan 2021 05:06:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=dOg1QiodelMO3s6QTltbxMRrhmZPrGedZT/RtjNu99c=; b=ST28h8YK/Crnldiv/p9MQDP3VykreTpd8muxiNoUUf9g5+fE9n89ABEVaGsA/DmZmM QGLLmEMwgzoT1zm9zXhE2fbBsIYFVHxwCdXWF73Cm7ZflJVLP/IxZAglhmHNz18rY0VR YbWoFf+iky/tjPSyZxqF7OZ1Q9Fb7azOxLiEV2JYdTMdlOBA5/xrmIIxRG3/GYpQo0oe oVk9M1Gulu6CpzXlQZ4RbpzQTV/fYc/qyybOsFKIMJJ5XBmhyhjloCWBEPfiHHIVjCkv b3L0LiAs9jhn1i0FeC3v4egOe61hvfQpBqtHuOGXYBdir4UGnsspTwxdEkpTBuhYz0z6 SWYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=dOg1QiodelMO3s6QTltbxMRrhmZPrGedZT/RtjNu99c=; b=mQYKKN0v4dKrI9H9Cyl6UBil7E1bG9piiunhoieaBjIKcrt8/13ke2RgDet/cUOewi Y3vWB/fp9quswtMbDdkhEB1AFxZMzvV73T9yjkwoAhDWmwJ2MRy69MVE1NTmWcSInOeC cXeFF/iJQTJXanB8lIflyRjQ8ZmS/ZDjHFzsJ4VN8Gm9BdDYl31gg/IMDAw2XaL4WeMY iQtJ/dzUkD98FkjVs9wjyDaxOF1so6TQ+f1CsA1qXlEPKgFNnSvW9gIx+BVVAFIrLSeV AVvvflfMwqRk2c3quTGLgqoYPnT8H5lxkzy9hP9myPjUGL3+Xxq28XfazlVHqxm1c9UW JoRQ== X-Gm-Message-State: AOAM533DWL/l+/dObWrR5VMc2mfSvWvqXs+jEu5Nvhy2l/hOUlaZbKag SKu2gIuSSF23TrsaGjLV46cRiD95JGhsFA== X-Google-Smtp-Source: ABdhPJxusPLuu8L6cOjZfu56gUEvavUCd/ln5OPZq6PolJbVhPzw4BWDFA5NKBaKijfx+MGp8ONe9qBn4wrRkw== Sender: "gprocida via sendgmr" X-Received: from tef.lon.corp.google.com ([2a00:79e0:d:110:a6ae:11ff:fe11:4f04]) (user=gprocida job=sendgmr) by 2002:a05:6214:913:: with SMTP id dj19mr575947qvb.33.1611580001730; Mon, 25 Jan 2021 05:06:41 -0800 (PST) Date: Mon, 25 Jan 2021 13:06:24 +0000 In-Reply-To: <20210125130625.2030186-1-gprocida@google.com> Message-Id: <20210125130625.2030186-4-gprocida@google.com> Mime-Version: 1.0 References: <20210125130625.2030186-1-gprocida@google.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog Subject: [PATCH dwarves 3/4] btf_encoder: Manually lay out updated ELF sections From: Giuliano Procida 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 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org pahole -J needs to do the following to an ELF file: * add or update the ".BTF" section * maybe update the section name string table * update the Section Header Table (SHT) libelf either takes full control of layout or requires the user to specify offset, size and alignment of all new and updated sections and headers. To avoid libelf moving program segments in particular, we position the ".BTF" and section name string table (typically named ".shstrtab") sections after all others. The SHT always lives at the end of the file. Note that the last section in an ELF file is normally the section name string table and any ".BTF" section will normally be second last. However, if these sections appear earlier, then we'll waste some space in the ELF file when we rewrite them. Signed-off-by: Giuliano Procida --- libbtf.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/libbtf.c b/libbtf.c index fb8e043..4726e16 100644 --- a/libbtf.c +++ b/libbtf.c @@ -742,9 +742,28 @@ static int btf_elf__write(const char *filename, struct btf *btf) } /* - * First we check if there is already a .BTF section present. + * The SHT is at the very end of the ELF and gets re-written in any case. + * + * We'll always add or update the .BTF section and when adding have to + * re-write the section name string table (usually named .shstrtab). In + * fact, as good citizens, we'll always leave the string table last, in + * case someone else wants to add a section. + * + * However, if .BTF or the section name string table are followed by + * further sections, we'll not try to be clever about shuffling + * everything else in the ELF file, we'll just leave some dead space. + * This actually happens in practice with vmlinux which has .strtab + * after .shstrtab, resulting in a (small) hole the size of the original + * .shstrtab. + */ + + /* + * First we look if there was already a .BTF section present and + * determine the first usable offset in the ELF (for .BTF and the + * section name table). */ elf_getshdrstrndx(elf, &strndx); + size_t high_water_mark = 0; Elf_Scn *btf_scn = 0; while ((scn = elf_nextscn(elf, scn)) != NULL) { shdr = gelf_getshdr(scn, &shdr_mem); @@ -753,7 +772,10 @@ static int btf_elf__write(const char *filename, struct btf *btf) char *secname = elf_strptr(elf, strndx, shdr->sh_name); if (strcmp(secname, ".BTF") == 0) { btf_scn = scn; - break; + } else if (elf_ndxscn(scn) != strndx) { + size_t limit = shdr->sh_offset + shdr->sh_size; + if (limit > high_water_mark) + high_water_mark = limit; } } @@ -762,6 +784,12 @@ static int btf_elf__write(const char *filename, struct btf *btf) fprintf(stderr, "%s: elf_getscn(strndx) failed\n", __func__); goto out; } + GElf_Shdr str_shdr_mem; + GElf_Shdr *str_shdr = gelf_getshdr(str_scn, &str_shdr_mem); + if (!str_shdr) { + fprintf(stderr, "%s: elf_getshdr(str_scn) failed\n", __func__); + goto out; + } size_t dot_btf_offset = 0; if (btf_scn) { @@ -793,6 +821,7 @@ static int btf_elf__write(const char *filename, struct btf *btf) str_data->d_buf = str_table; str_data->d_size = new_str_size; elf_flagdata(str_data, ELF_C_SET, ELF_F_DIRTY); + str_shdr->sh_size = new_str_size; /* Create a new section */ btf_scn = elf_newscn(elf); @@ -812,12 +841,15 @@ static int btf_elf__write(const char *filename, struct btf *btf) /* (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_off = 0; 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 */ + size_t new_btf_offset = high_water_mark; + size_t new_btf_size = raw_btf_size; GElf_Shdr btf_shdr_mem; GElf_Shdr *btf_shdr = gelf_getshdr(btf_scn, &btf_shdr_mem); if (!btf_shdr) { @@ -829,6 +861,8 @@ static int btf_elf__write(const char *filename, struct btf *btf) btf_shdr->sh_flags = 0; if (dot_btf_offset) btf_shdr->sh_name = dot_btf_offset; + btf_shdr->sh_offset = new_btf_offset; + btf_shdr->sh_size = new_btf_size; btf_shdr->sh_type = SHT_PROGBITS; if (!gelf_update_shdr(btf_scn, btf_shdr)) { fprintf(stderr, "%s: gelf_update_shdr failed: %s\n", @@ -836,6 +870,32 @@ static int btf_elf__write(const char *filename, struct btf *btf) goto out; } + /* Update section name string table */ + size_t new_str_offset = new_btf_offset + new_btf_size; + str_shdr->sh_offset = new_str_offset; + if (!gelf_update_shdr(str_scn, str_shdr)) { + fprintf(stderr, "gelf_update_shdr failed\n"); + goto out; + } + + /* Update SHT, allowing for ELF64 alignment */ + size_t sht_offset = roundup(new_str_offset + str_shdr->sh_size, 8); + ehdr->e_shoff = sht_offset; + if (!gelf_update_ehdr(elf, ehdr)) { + fprintf(stderr, "gelf_update_ehdr failed\n"); + goto out; + } + + if (btf_elf__verbose) { + fprintf(stderr, ".BTF [0x%lx, +0x%lx)\n", + btf_shdr->sh_offset, btf_shdr->sh_size); + fprintf(stderr, ".shstrtab [0x%lx, +0x%lx)\n", + str_shdr->sh_offset, str_shdr->sh_size); + fprintf(stderr, "SHT [0x%lx, +%d*0x%x)\n", + ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize); + } + + elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT); if (elf_update(elf, ELF_C_NULL) < 0) { fprintf(stderr, "%s: elf_update (layout) failed: %s\n", __func__, elf_errmsg(elf_errno())); From patchwork Mon Jan 25 13:06:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 12045497 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8DF56C433E0 for ; Tue, 26 Jan 2021 05:37:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5992E2223D for ; Tue, 26 Jan 2021 05:37:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388010AbhAZFhY (ORCPT ); Tue, 26 Jan 2021 00:37:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55786 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728622AbhAYNJ2 (ORCPT ); Mon, 25 Jan 2021 08:09:28 -0500 Received: from mail-wr1-x44a.google.com (mail-wr1-x44a.google.com [IPv6:2a00:1450:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 67343C061794 for ; Mon, 25 Jan 2021 05:06:45 -0800 (PST) Received: by mail-wr1-x44a.google.com with SMTP id u3so7966656wri.19 for ; Mon, 25 Jan 2021 05:06:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=dHCmE0oVXoubM3rTHyQSPX2MJEXLHemPJUmiQIz1gjE=; b=SFOnqGDYvQ3UMYg+Xxq0/jYMkh+nolREupxeeXaZMo7t5sbzBXzhvyD5ZZrXjZHi56 6yyQt6i+aptZKrd6GbcvAUOhf1M5c5fHGYt0F3jPjGCwknFrb8GBxUbScLTCXjZ/Kjsh MG1RbRLYNJ/p1+xjcOOLWENFojsvHpETaL8oUJjGPqL8bz6mNHsJxnZFKh73VkenHEI+ h0y5yuf8DTlo2A0ODTBssz1IVUjCPI+B/3N0ZbzHwaeDfCfsm0fM2JW1lnZ28ih3JZx2 Ouyq8rBiyKRIr8wv8RIdeICRhz6gxKtkiQgM3aJ9A/RctlU2CNK1yyVVBjL91Mefzs41 RZoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=dHCmE0oVXoubM3rTHyQSPX2MJEXLHemPJUmiQIz1gjE=; b=izReoPnpNUzfjxUKlXTtQJkhVoAIyznFZQ2UttrsnCiUQHYcCjpjfSlFFdAKiapUql GaJSs+7hmD6hsy1bDw/EIHJ2dQCkU0jOcQy1o9MKccnm7qLkEJzUi3+D4hkH2FZWEpSo Spj0RoXJjhOW/7gBVnbYi8ITNDJypdzEanaDJuAMMbRyLsV+QEBE8UJolSBrl0UH4jSy 42H+19QhonG5W+cgdrWGjUeMGXkxw9duOo6g1J9PSALOfbgW+ua2Tkvbi1H1tz14H2M9 a2wqOAZGggCG7Shh2fsH4mno7oLd6tPdY/ofyJYCkYozo1vgm14WcVxAwj8XuLhMIzMv nHqw== X-Gm-Message-State: AOAM5328cjBVBfiIhTxh+W+CwsqSg6xi+osZlN2kURVzfgcy/CoZZkfS 8VaDjf9pmcX/JA4UbigJl6h6fOzZjt+8hA== X-Google-Smtp-Source: ABdhPJwLbiQP/xW54xaHyoWge2cRYZKMzVdicac9X6ZmG5acd/9J8zAyuqNenerL/j1SSHfRzykZLtvkQw3dOA== Sender: "gprocida via sendgmr" X-Received: from tef.lon.corp.google.com ([2a00:79e0:d:110:a6ae:11ff:fe11:4f04]) (user=gprocida job=sendgmr) by 2002:a1c:e0d4:: with SMTP id x203mr49589wmg.160.1611580004135; Mon, 25 Jan 2021 05:06:44 -0800 (PST) Date: Mon, 25 Jan 2021 13:06:25 +0000 In-Reply-To: <20210125130625.2030186-1-gprocida@google.com> Message-Id: <20210125130625.2030186-5-gprocida@google.com> Mime-Version: 1.0 References: <20210125130625.2030186-1-gprocida@google.com> X-Mailer: git-send-email 2.30.0.280.ga3ce27912f-goog Subject: [PATCH dwarves 4/4] btf_encoder: Align .BTF section to 8 bytes From: Giuliano Procida 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 Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org This is to avoid misaligned access to BTF type structs when memory-mapping ELF sections. Signed-off-by: Giuliano Procida --- libbtf.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libbtf.c b/libbtf.c index 4726e16..fa00053 100644 --- a/libbtf.c +++ b/libbtf.c @@ -755,7 +755,13 @@ static int btf_elf__write(const char *filename, struct btf *btf) * This actually happens in practice with vmlinux which has .strtab * after .shstrtab, resulting in a (small) hole the size of the original * .shstrtab. + * + * We'll align .BTF to 8 bytes to cater for all architectures. It'd be + * nice if we could fetch this value from somewhere. The BTF + * specification does not discuss alignment and its trailing string + * table is not currently padded to any particular alignment. */ + const size_t btf_alignment = 8; /* * First we look if there was already a .BTF section present and @@ -848,8 +854,8 @@ static int btf_elf__write(const char *filename, struct btf *btf) elf_flagdata(btf_data, ELF_C_SET, ELF_F_DIRTY); /* Update .BTF section in the SHT */ - size_t new_btf_offset = high_water_mark; - size_t new_btf_size = raw_btf_size; + size_t new_btf_offset = roundup(high_water_mark, btf_alignment); + size_t new_btf_size = roundup(raw_btf_size, btf_alignment); GElf_Shdr btf_shdr_mem; GElf_Shdr *btf_shdr = gelf_getshdr(btf_scn, &btf_shdr_mem); if (!btf_shdr) { @@ -857,6 +863,7 @@ static int btf_elf__write(const char *filename, struct btf *btf) __func__, elf_errmsg(elf_errno())); goto out; } + btf_shdr->sh_addralign = btf_alignment; btf_shdr->sh_entsize = 0; btf_shdr->sh_flags = 0; if (dot_btf_offset)