From patchwork Mon Feb 1 17:25:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 12059501 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 C3131C433DB for ; Mon, 1 Feb 2021 17:27:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7DC3864EA9 for ; Mon, 1 Feb 2021 17:27:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231591AbhBAR0p (ORCPT ); Mon, 1 Feb 2021 12:26:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38628 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231476AbhBAR0l (ORCPT ); Mon, 1 Feb 2021 12:26:41 -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 9FA09C061786 for ; Mon, 1 Feb 2021 09:26:01 -0800 (PST) Received: by mail-qt1-x84a.google.com with SMTP id v13so1145363qtq.18 for ; Mon, 01 Feb 2021 09:26:01 -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=TfWRYi9hxejy8NpU6fXU34oPw27hyyY5z9BCAPqd/v0=; b=Wyv3LLjAmessGhQSIy4qCE/rDzqXGuhA/CWvBeQkZu5lVuuoyiBJ91EE4YnZS+AmBF 3u5+Iot5gYRGEeHoHUjMFVdbN1IRpEwpEVCzJF56F6wR0MJmyQHisyDZzRts7b00Vl17 wMLF/nUW6vLLTQYdF74xVFVyGGCAjbdbMH/j+YQOrcJJR1EvBdaeYZmEHDh3rfZnYywT xsgRCf6HhfyXKDGc0iIxUvBzl/0hDRXSWoJmRHmkOClLcLz6upbEFlclUqXMiifvUmIP md45DN77fqRD7U/ANwrhJKvw/ElMfuu97SHC24tfsEcJbi9/ElXinDL7k9WfNzF9FrLt q0nw== 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=TfWRYi9hxejy8NpU6fXU34oPw27hyyY5z9BCAPqd/v0=; b=ot357uNai9f67YHMqKxTwnpiYei4Ljqf7Uf5KTdihuZgL0KziMRHmywOjfeQWCzYtG qXGHccrL6gPuWry6Q35hsz7PkVm/fFBWstEqnIkr/lBaGHkhdVTZxflK7fB2oG4QUjHD GvGbgOAUQGPe7hYBouxVdqdjuV1BywpPRYvcFf277P1QC4xzSpbq7c9tFRXGn0kqt1Cy RD7hRHYS+p6N+YZs3ql0RqW7ikO5AhFfx+LRIHYhxzN/Dd4Kgiws88S0hcdvaFZpjo7x GUKlUO17iqlzwAWbx8RUM5ice2il8dmpy+Xh7HTW2UmIyr2gpuXqifh5BCrFSmWXZ+Zn LHKA== X-Gm-Message-State: AOAM531Scpg9alSR4637nrlO08iTxJUOwBV8Dtn8AkWDQGkmxDJr5AEG F093QbWNBqu+Wy75Y9wwokZ07D8RzMFwzA== X-Google-Smtp-Source: ABdhPJzWt/rbL1FTsJQCGX9jKuXIoAGGUeAPJ4rWxNzOXJrxIvWHKg2h3oXa5LFASidKJ+gWfnByhyzh84qaAQ== Sender: "gprocida via sendgmr" X-Received: from tef.lon.corp.google.com ([2a00:79e0:d:210:6893:b158:d9db:277c]) (user=gprocida job=sendgmr) by 2002:a05:6214:1110:: with SMTP id e16mr16097805qvs.62.1612200360663; Mon, 01 Feb 2021 09:26:00 -0800 (PST) Date: Mon, 1 Feb 2021 17:25:27 +0000 In-Reply-To: <20210201172530.1141087-1-gprocida@google.com> Message-Id: <20210201172530.1141087-2-gprocida@google.com> Mime-Version: 1.0 References: <87a83353155506cc02141e6e4108d89aa4e7d284> <20210201172530.1141087-1-gprocida@google.com> X-Mailer: git-send-email 2.30.0.365.g02bc693789-goog Subject: [PATCH dwarves v2 1/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 and indeed offsets of existing sections are likely to change. Signed-off-by: Giuliano Procida --- libbtf.c | 134 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 46 deletions(-) diff --git a/libbtf.c b/libbtf.c index 81b1b36..5b91d3a 100644 --- a/libbtf.c +++ b/libbtf.c @@ -698,6 +698,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) { @@ -740,74 +741,115 @@ 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 (strtab) failed\n", __func__); + 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; + 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; } + } - err = 0; - unlink: - unlink(tmp_fn); + /* (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 = SHF_ALLOC; + 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; + } + + 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 Feb 1 17:25:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 12059507 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=unavailable 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 B83BCC432C3 for ; Mon, 1 Feb 2021 17:27:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 865A664EB9 for ; Mon, 1 Feb 2021 17:27:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231599AbhBAR1I (ORCPT ); Mon, 1 Feb 2021 12:27:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38646 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231233AbhBAR0o (ORCPT ); Mon, 1 Feb 2021 12:26:44 -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 9C577C06178A for ; Mon, 1 Feb 2021 09:26:04 -0800 (PST) Received: by mail-wr1-x449.google.com with SMTP id n14so10807704wru.6 for ; Mon, 01 Feb 2021 09:26:04 -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=YDxToULhiLjuBex0deTClM4Ud7mf2JtShhU/pcWFbzY=; b=WNS8a5ZnSlcq7C7ERfxNj7fFFK1TEpNiP9RKtYX3XWZI+KQwmWFBnlnKYMVg2OWRiQ brEM50ab1ooN7wgIBVoE37UqX13dR2N+pE+RAnxNV0ycDxV7a39kC/EgLmM5Mlj6YoUs KNTAW/XWOgSFG5PPf3bOuzN9bxFQ8fxwbVg1gDRErJKWnLupbvdL31IRKRZ9pRlkSHOk UTEAcH4Sqts+sYagSqWVd5XvVo9LqfBKeYnZDEa8wbkTY/L1JWAAGrYjjoIiDa6InNtd 6v01jNBfaNYXLGtmyDZPgcGlt/cNLITKvD92mO/gzVDXH3+QbpvNSDQQcxej3XUVRR+Y JN4g== 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=YDxToULhiLjuBex0deTClM4Ud7mf2JtShhU/pcWFbzY=; b=tGtQaONUcxIafRBDe/b6vWj7fm5IxZmGdBt5D+SFDfwk2PFlyNjCWG30njjnXjAKOk Q5WamQP6RBVDtaOX09UHnhPMKaKHFQhIaybv6oT9sWytbd6ucN+fa7XxwRSokKnQ6TYs 7oaLWDthoum7TTCe43U6I3Fdh0ncujuRUR7+o2bL33Un80SYcG8EGkVnqq2GgUvkHgkE nacKhrL7egqgozOEpaH63Yu4Ieq+ZGL/BepPszKJR591qG2BfpIXW1VfX/4zYEWWr+BS j4Fg25+kNiRADS2Cx3IEr8GCSzvjSK5ppXPIugaYgzjx9PZV0DI9h4Fa9TfqrOcu+GRd 9B8Q== X-Gm-Message-State: AOAM530VJ4P62aakJAhF5BstTGX83UNHciYo+MwyJzSFAfZmyf7F2QHs cifpDCif6DrSJuxc4pSdGwpfnbTtsCvjcw== X-Google-Smtp-Source: ABdhPJzrbXIdfE7y90Snjx52gZc+gdOyBkufbbsfFR/XzO3U/FHYpXSbDVsV9ABShiiwSsJ1VO+AQHEXF5RNhA== Sender: "gprocida via sendgmr" X-Received: from tef.lon.corp.google.com ([2a00:79e0:d:210:6893:b158:d9db:277c]) (user=gprocida job=sendgmr) by 2002:a7b:c044:: with SMTP id u4mr87442wmc.1.1612200362886; Mon, 01 Feb 2021 09:26:02 -0800 (PST) Date: Mon, 1 Feb 2021 17:25:28 +0000 In-Reply-To: <20210201172530.1141087-1-gprocida@google.com> Message-Id: <20210201172530.1141087-3-gprocida@google.com> Mime-Version: 1.0 References: <87a83353155506cc02141e6e4108d89aa4e7d284> <20210201172530.1141087-1-gprocida@google.com> X-Mailer: git-send-email 2.30.0.365.g02bc693789-goog Subject: [PATCH dwarves v2 2/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 5b91d3a..6e06a58 100644 --- a/libbtf.c +++ b/libbtf.c @@ -741,9 +741,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); @@ -752,7 +771,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; } } @@ -761,6 +783,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) { @@ -791,6 +819,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); @@ -810,12 +839,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) { @@ -827,6 +859,8 @@ static int btf_elf__write(const char *filename, struct btf *btf) btf_shdr->sh_flags = SHF_ALLOC; 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", @@ -834,6 +868,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 Feb 1 17:25:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 12059505 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 5FE1FC43333 for ; Mon, 1 Feb 2021 17:27:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2C41464EC7 for ; Mon, 1 Feb 2021 17:27:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231603AbhBAR1H (ORCPT ); Mon, 1 Feb 2021 12:27:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38658 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231599AbhBAR0q (ORCPT ); Mon, 1 Feb 2021 12:26:46 -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 1A7F8C06178C for ; Mon, 1 Feb 2021 09:26:07 -0800 (PST) Received: by mail-wr1-x44a.google.com with SMTP id j8so10754968wrx.17 for ; Mon, 01 Feb 2021 09:26:07 -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=2RQrtF4Yu/7TyUfyq3im7rIOCZ1idrksD+9OKNcN2CM=; b=KN1IiaHpAKfiWqYWp+yXLt0HSXylS1CHtzydscr1Z+p3MKyQ/1bbQuzEDeUKJ1+faG ADX3YTaaoft30bmkGRRv65kb11Y0O/tqyQdD8hjANJkNJLx4cmIyjhXqtBwwBGCsI7H3 p6rYN1smuiWDyWhqtRR0M/BSQqJE+ReW6ftnJjh1aCoYud2J0vUPWd6s438Ni4M9gWZT 3rb9354DJOZn7Nh7FE7yje+lFPs2bjp9XzYKBaS+qKxmYcZBrlhCGms+YVUeWTDn1+Je ygipHY6YdjONdFHFAmSRCUchgEtmlgoXBY1CQ+9KUGLkmc+RtD9zwBois5Zah1F04qw1 0JKA== 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=2RQrtF4Yu/7TyUfyq3im7rIOCZ1idrksD+9OKNcN2CM=; b=JKyLBxP0itvpmxxnMiVcQYhMd446rtMNAh9PnX1LsXHVYiHxupsmIzj0/OaYqpJNUZ HgtvAUdsmdjrXge2agvV9EZKZtHwzPSQnk9c/2BX9vaqfOsXWM9MxXPnzLeF55KlrY2C SSyw3Ihbb5TYMk0whAyuO/HFRgKwXh6BpBSvcXPxQ+IxgOvL5U6lqz4JwDBN5PJDMbj/ 0F25+067ibFbPxT/OYW6AyKyJbg2XbKkRfnge5LbNwdTqfvXjPSGLDQyOgYYSLvzWmSI 2A/ezqx07AosmAip1rxvqtHqpq/TwKCADaOQISRONsk3Dx6bM6as9qJSHlFiEzGCId6m VCBw== X-Gm-Message-State: AOAM532wvEl2wYUxHVA3lDmneFv4hBJXqatUXwE2SFhbbPHyvL1ZnYAx e3km6j7v+T08WygVNbe7p3nILwWTNgr9FQ== X-Google-Smtp-Source: ABdhPJzK+cSTbTHYsovUlZQ9WWYjGZmtSASuzYrI0Lfjb8GQccezB8Z/Vy72r7WQ5RS4vt7eHQ+xHhlVFkuPjw== Sender: "gprocida via sendgmr" X-Received: from tef.lon.corp.google.com ([2a00:79e0:d:210:6893:b158:d9db:277c]) (user=gprocida job=sendgmr) by 2002:a05:600c:35c9:: with SMTP id r9mr87875wmq.0.1612200365467; Mon, 01 Feb 2021 09:26:05 -0800 (PST) Date: Mon, 1 Feb 2021 17:25:29 +0000 In-Reply-To: <20210201172530.1141087-1-gprocida@google.com> Message-Id: <20210201172530.1141087-4-gprocida@google.com> Mime-Version: 1.0 References: <87a83353155506cc02141e6e4108d89aa4e7d284> <20210201172530.1141087-1-gprocida@google.com> X-Mailer: git-send-email 2.30.0.365.g02bc693789-goog Subject: [PATCH dwarves v2 3/4] btf_encoder: Add .BTF as a loadable segment 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 In addition to adding .BTF to the Section Header Table, we also need to add it to the Program Header Table and rewrite the PHT's description of itself. The segment as loadbale, at address 0 and read-only. Signed-off-by: Giuliano Procida --- libbtf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/libbtf.c b/libbtf.c index 6e06a58..048a873 100644 --- a/libbtf.c +++ b/libbtf.c @@ -699,6 +699,7 @@ static int btf_elf__write(const char *filename, struct btf *btf) int fd, err = -1; size_t strndx; void *str_table = NULL; + GElf_Phdr *pht = NULL; fd = open(filename, O_RDWR); if (fd < 0) { @@ -900,6 +901,47 @@ static int btf_elf__write(const char *filename, struct btf *btf) goto out; } + size_t phnum = 0; + if (!elf_getphdrnum(elf, &phnum)) { + pht = malloc((phnum + 1) * sizeof(GElf_Phdr)); + if (!pht) { + fprintf(stderr, "%s: malloc (PHT) failed\n", __func__); + goto out; + } + for (size_t ix = 0; ix < phnum; ++ix) { + if (!gelf_getphdr(elf, ix, &pht[ix])) { + fprintf(stderr, + "%s: gelf_getphdr(%zu) failed: %s\n", + __func__, ix, elf_errmsg(elf_errno())); + goto out; + } + if (pht[ix].p_type == PT_PHDR) { + size_t fsize = gelf_fsize(elf, ELF_T_PHDR, + phnum+1, EV_CURRENT); + pht[ix].p_memsz = pht[ix].p_filesz = fsize; + } + } + pht[phnum].p_type = PT_LOAD; + pht[phnum].p_offset = btf_shdr->sh_offset; + pht[phnum].p_memsz = pht[phnum].p_filesz = btf_shdr->sh_size; + pht[phnum].p_vaddr = pht[phnum].p_paddr = 0; + pht[phnum].p_flags = PF_R; + void *phdr = gelf_newphdr(elf, phnum+1); + if (!phdr) { + fprintf(stderr, "%s: gelf_newphdr failed: %s\n", + __func__, elf_errmsg(elf_errno())); + goto out; + } + for (size_t ix = 0; ix < phnum+1; ++ix) { + if (!gelf_update_phdr(elf, ix, &pht[ix])) { + fprintf(stderr, + "%s: gelf_update_phdr(%zu) failed: %s\n", + __func__, ix, elf_errmsg(elf_errno())); + goto out; + } + } + } + if (elf_update(elf, ELF_C_WRITE) < 0) { fprintf(stderr, "%s: elf_update (write) failed: %s\n", __func__, elf_errmsg(elf_errno())); @@ -908,6 +950,8 @@ static int btf_elf__write(const char *filename, struct btf *btf) err = 0; out: + if (pht) + free(pht); if (str_table) free(str_table); if (fd != -1) From patchwork Mon Feb 1 17:25:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 12059503 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 063B5C4332E for ; Mon, 1 Feb 2021 17:27:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CD79564EA9 for ; Mon, 1 Feb 2021 17:27:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231760AbhBAR1H (ORCPT ); Mon, 1 Feb 2021 12:27:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38668 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231611AbhBAR0s (ORCPT ); Mon, 1 Feb 2021 12:26:48 -0500 Received: from mail-qv1-xf49.google.com (mail-qv1-xf49.google.com [IPv6:2607:f8b0:4864:20::f49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CEE8DC061794 for ; Mon, 1 Feb 2021 09:26:08 -0800 (PST) Received: by mail-qv1-xf49.google.com with SMTP id q37so11175265qvf.14 for ; Mon, 01 Feb 2021 09:26:08 -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=SzX/76WK1bIQFSNZsX1p6vCVFi30KIn33vpgS3dU+T4=; b=LgqnBPeuMxz96fcoXG5DtjiqfY9PVITepDTqOVFxBLdnxBITpfBBXmBUSK/htFJHnG bKCJd0W/eJYdHdh2AnWlGmPwWjsJbYyzGLyi1vlxuFT/mY34ToAzjyKnFxVJMPOYQvgF HXjv6vtnMEMvtMqrCoM2KU6O8aBI35VDgKW2axvFXZ8gYSnh8k87bDhG2roNzPvHMY4f pm5f5kGmdHGO5bg5z+LwoQ+zJGATppRQvM9Qilfg9BmuOS1HKbX7O3AWiQ3e4TSZTx+H 8sypdPBmmqkhbZ3Aw5j5nfjW8e4EoxFJvnMr4gADe0XZ7/kR6cKEDSq3JlQgR9Rfm9vy O95w== 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=SzX/76WK1bIQFSNZsX1p6vCVFi30KIn33vpgS3dU+T4=; b=KGIBu6Fu/ZX9XsLho+cUucF5hR1sQGBPwug7tARRhCY8+RdUFAUVndolrwCHo8tma+ saxG58QljsnY9329zKiYLIBWYeyUuelj5ezEPEzWf+yV8FlwlyngYfb3sg3gc7I/r0qa GEBo8wBNV1w4B7JW1HqHvIu+tKMkZ1F5VfXwYbParG4lyCFazTI/zhewj/kI4FCqbIhA JSAkyxfPjRttUUBBCJZgb2IaWA7spbV9LcuCBcbLxUTSUtjUZ39mrYeWTAUB8fZrh9co 21R7jzf00WNkq6A2XHcw/QpYULApr2U4v3aiJnd2UGBPHoYvyt72lmsnP0hOc/P4Zo+I pepg== X-Gm-Message-State: AOAM530EFs8xwc9mZDFzYBp4RSH43rbUDllHIaQ4FQsgK01oq+lhl8Aw /lpT3yrWZFkhpyGbt5Lb1sfUDRQrghgqJQ== X-Google-Smtp-Source: ABdhPJz0qDqRzI0ZwKQCmtohyB/H8S7feCG8hVcGtdHRrP+L16/1OtQntX4HRlG2xd8+QNlrmI8qzLWasj94hg== Sender: "gprocida via sendgmr" X-Received: from tef.lon.corp.google.com ([2a00:79e0:d:210:6893:b158:d9db:277c]) (user=gprocida job=sendgmr) by 2002:a05:6214:ce:: with SMTP id f14mr12876974qvs.25.1612200367896; Mon, 01 Feb 2021 09:26:07 -0800 (PST) Date: Mon, 1 Feb 2021 17:25:30 +0000 In-Reply-To: <20210201172530.1141087-1-gprocida@google.com> Message-Id: <20210201172530.1141087-5-gprocida@google.com> Mime-Version: 1.0 References: <87a83353155506cc02141e6e4108d89aa4e7d284> <20210201172530.1141087-1-gprocida@google.com> X-Mailer: git-send-email 2.30.0.365.g02bc693789-goog Subject: [PATCH dwarves v2 4/4] btf_encoder: Align .BTF section/segment 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 | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libbtf.c b/libbtf.c index 048a873..ae99a93 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 @@ -847,8 +853,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) { @@ -856,6 +862,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 = SHF_ALLOC; if (dot_btf_offset) @@ -926,6 +933,7 @@ static int btf_elf__write(const char *filename, struct btf *btf) pht[phnum].p_memsz = pht[phnum].p_filesz = btf_shdr->sh_size; pht[phnum].p_vaddr = pht[phnum].p_paddr = 0; pht[phnum].p_flags = PF_R; + pht[phnum].p_align = btf_alignment; void *phdr = gelf_newphdr(elf, phnum+1); if (!phdr) { fprintf(stderr, "%s: gelf_newphdr failed: %s\n",