Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp103212ybz; Fri, 24 Apr 2020 12:33:48 -0700 (PDT) X-Google-Smtp-Source: APiQypIdU+umMVcU4Tn6/5zKNWTHrRvavYPlvvyBxHBSdagLY2NIm7mRRKny+P9wDWUrIv5TR/BA X-Received: by 2002:a50:ea87:: with SMTP id d7mr3291386edo.48.1587756828094; Fri, 24 Apr 2020 12:33:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1587756828; cv=none; d=google.com; s=arc-20160816; b=MnjezAlKhate4m5tmQe0QVBmMIyaAzqkECRO3I8kk9CYoEcyNE1I0j1CLrI77boZ2x MJ4sIuL8RlNgCQa/jRmWercnagoVKegGcE9u1FhdK4uG5WMeYIPmNsU0y8SFHSaeDru+ 8b9zCP811T10CqLK5d5oFl2407WJSmJ9JRG+6xIA2eIf0vlW9z2O55yH5wN03RTbLoEV 3Eq8HLVYNgx5hwrenKXAN8maTXNoewEJvKExnD7HF0JEawz74o7TJAekcTbgQk8C7uoz oLhWx9lpR5j15uqFz+e+ggIxhOwyd0exByj8kXPm0mIErTlMF6Ua6JepPp8JjGblS4rK Qu9g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:dkim-signature; bh=QXUU1CaDn20CRklY2AMQEDvRUmDsb17NnJaSIr9zUvQ=; b=yQSFM+Njs97qM69eYIF7VUU0IAFDYsOK1J/74rS/fuEKt0frqYDMSIsfmxM579jPDq BRv2p5HZnAI/tSizPxNJIUMqF0OenHUhU2hyptgslqkt21KfHLJjlKGd9wmaaPYPg2PO tgPo//kTrxJopX0gsovw+d/PUeSb42Xj//9pkecNx+CDGCYtaYK3LvKeNE4zMzPV2HuP jT6SrFyI3vsxYi4Y+kza9N3ToqPrwC+0G94pC7LNq96cggv3d9i4hYUZOuxalmgdyZsF vz52sRZg0vuTqSmNWZOWAn06qOGFvSMeaypYVFzm4KlO2MoHeZjsVBEut8zjfsnd8aea Z3sw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=PyNhVKiV; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id d22si2960683edj.11.2020.04.24.12.33.23; Fri, 24 Apr 2020 12:33:48 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=PyNhVKiV; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729320AbgDXTav (ORCPT + 99 others); Fri, 24 Apr 2020 15:30:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34468 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1725970AbgDXTau (ORCPT ); Fri, 24 Apr 2020 15:30:50 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DB592C09B048 for ; Fri, 24 Apr 2020 12:30:50 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id y21so8714385pjn.5 for ; Fri, 24 Apr 2020 12:30:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=QXUU1CaDn20CRklY2AMQEDvRUmDsb17NnJaSIr9zUvQ=; b=PyNhVKiVHcwOLEiMvqgYbNlt5r4G4qtR+syy0A4olTsR8GUV3DhlTH45oH64gsPyti 3B/oxheiZF3tfaEWuEsEQex/8dEjzcgTeSPOxwQOAjU/QQ3vjPR0PzTO4a+CItUrUrDM K2PAP1GZx7e7aZpcuc7rXLzqxMlHeJ5QPNme4eCtxH7zi5B4zxfRYMbDTXhAmC/cDrY7 9zOJbiSPOg5NfUMvMNYv6CC8Kf1MpLRBocOTQWpgYMhrcZGvXkjCM6buXaiuHHNVvBA2 WBtokK7QwPeutNlwBoP/bTUGTZqwAz/sdIsBZT7Zld6tC4q7IZvRgd6rgEjgPuknvr0J yY1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=QXUU1CaDn20CRklY2AMQEDvRUmDsb17NnJaSIr9zUvQ=; b=DXrwYKEj8ZeNpufN/a/VYXgq4cBYnsiv0DsjB1OxHv78GFf5OUTKafEmranMzLL64Y 1Z9u8aJcB/hZBWfn+69fDxaA+gAhMaLAOodmSxv5S9Bx0aO+9184W+4bL9efcfULIVwy hlWGuJlXyBDAhfcGZbQbX54U548UAYND7nlOOfOUmW2e3rnbyrZm92cWKaev55P+1mWR 0xZY4EqIhw0hTCB/hTN4kuTepVzLr52IIadH+2iXN6Prr+Hsf1aT2b9MSL8XsvN1//rN O1J1RYy6g/fyFcZqdcp4BbIQMYigB6pvwbhVIw/0wtKvW/zifAPMGLMZZ3UkxAatMjBf 59VQ== X-Gm-Message-State: AGi0PuZa+TgT+9MjTTQaIxU8HmdjPlWk1senp7DhqtDV0/8n94HnjTer euliQKyz+lt5TQmKR8c4Zs6wZl6WBL+gyIQ4kGU= X-Received: by 2002:a17:90a:8415:: with SMTP id j21mr8013956pjn.12.1587756650010; Fri, 24 Apr 2020 12:30:50 -0700 (PDT) Date: Fri, 24 Apr 2020 12:30:46 -0700 In-Reply-To: <20200422232417.72162-1-samitolvanen@google.com> Message-Id: <20200424193046.160744-1-samitolvanen@google.com> Mime-Version: 1.0 References: <20200422232417.72162-1-samitolvanen@google.com> X-Mailer: git-send-email 2.26.2.303.gf8c07b1a785-goog Subject: [PATCH v2] recordmcount: support >64k sections From: Sami Tolvanen To: "Steven Rostedt (VMware)" , Matt Helsley , Greg Kroah-Hartman , Thomas Gleixner , "Naveen N. Rao" , Kees Cook Cc: linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, Sami Tolvanen Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When compiling a kernel with Clang and LTO, we need to run recordmcount on vmlinux.o with a large number of sections, which currently fails as the program doesn't understand extended section indexes. This change adds support for processing binaries with >64k sections. Signed-off-by: Sami Tolvanen --- Changes in v2: - Switched to unsigned int for (old|new)_shnum in append_func. - Added set_shnum and find_symtab helper functions and moved the new logic there. --- scripts/recordmcount.h | 98 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 6 deletions(-) diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h index 74eab03e31d4..f9b19524da11 100644 --- a/scripts/recordmcount.h +++ b/scripts/recordmcount.h @@ -29,6 +29,11 @@ #undef has_rel_mcount #undef tot_relsize #undef get_mcountsym +#undef find_symtab +#undef get_shnum +#undef set_shnum +#undef get_shstrndx +#undef get_symindex #undef get_sym_str_and_relp #undef do_func #undef Elf_Addr @@ -58,6 +63,11 @@ # define __has_rel_mcount __has64_rel_mcount # define has_rel_mcount has64_rel_mcount # define tot_relsize tot64_relsize +# define find_symtab find_symtab64 +# define get_shnum get_shnum64 +# define set_shnum set_shnum64 +# define get_shstrndx get_shstrndx64 +# define get_symindex get_symindex64 # define get_sym_str_and_relp get_sym_str_and_relp_64 # define do_func do64 # define get_mcountsym get_mcountsym_64 @@ -91,6 +101,11 @@ # define __has_rel_mcount __has32_rel_mcount # define has_rel_mcount has32_rel_mcount # define tot_relsize tot32_relsize +# define find_symtab find_symtab32 +# define get_shnum get_shnum32 +# define set_shnum set_shnum32 +# define get_shstrndx get_shstrndx32 +# define get_symindex get_symindex32 # define get_sym_str_and_relp get_sym_str_and_relp_32 # define do_func do32 # define get_mcountsym get_mcountsym_32 @@ -173,6 +188,67 @@ static int MIPS_is_fake_mcount(Elf_Rel const *rp) return is_fake; } +static unsigned int get_symindex(Elf_Sym const *sym, Elf32_Word const *symtab, + Elf32_Word const *symtab_shndx) +{ + unsigned long offset; + int index; + + if (sym->st_shndx != SHN_XINDEX) + return w2(sym->st_shndx); + + offset = (unsigned long)sym - (unsigned long)symtab; + index = offset / sizeof(*sym); + + return w(symtab_shndx[index]); +} + +static unsigned int get_shnum(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0) +{ + if (shdr0 && !ehdr->e_shnum) + return w(shdr0->sh_size); + + return w2(ehdr->e_shnum); +} + +static void set_shnum(Elf_Ehdr *ehdr, Elf_Shdr *shdr0, unsigned int new_shnum) +{ + if (new_shnum >= SHN_LORESERVE) { + ehdr->e_shnum = 0; + shdr0->sh_size = w(new_shnum); + } else + ehdr->e_shnum = w2(new_shnum); +} + +static int get_shstrndx(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0) +{ + if (ehdr->e_shstrndx != SHN_XINDEX) + return w2(ehdr->e_shstrndx); + + return w(shdr0->sh_link); +} + +static void find_symtab(Elf_Ehdr *const ehdr, Elf_Shdr const *shdr0, + unsigned const nhdr, Elf32_Word **symtab, + Elf32_Word **symtab_shndx) +{ + Elf_Shdr const *relhdr; + unsigned k; + + *symtab = NULL; + *symtab_shndx = NULL; + + for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) { + if (relhdr->sh_type == SHT_SYMTAB) + *symtab = (void *)ehdr + relhdr->sh_offset; + else if (relhdr->sh_type == SHT_SYMTAB_SHNDX) + *symtab_shndx = (void *)ehdr + relhdr->sh_offset; + + if (*symtab && *symtab_shndx) + break; + } +} + /* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ static int append_func(Elf_Ehdr *const ehdr, Elf_Shdr *const shstr, @@ -188,10 +264,12 @@ static int append_func(Elf_Ehdr *const ehdr, char const *mc_name = (sizeof(Elf_Rela) == rel_entsize) ? ".rela__mcount_loc" : ".rel__mcount_loc"; - unsigned const old_shnum = w2(ehdr->e_shnum); uint_t const old_shoff = _w(ehdr->e_shoff); uint_t const old_shstr_sh_size = _w(shstr->sh_size); uint_t const old_shstr_sh_offset = _w(shstr->sh_offset); + Elf_Shdr *const shdr0 = (Elf_Shdr *)(old_shoff + (void *)ehdr); + unsigned int const old_shnum = get_shnum(ehdr, shdr0); + unsigned int const new_shnum = 2 + old_shnum; /* {.rel,}__mcount_loc */ uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size); uint_t new_e_shoff; @@ -201,6 +279,8 @@ static int append_func(Elf_Ehdr *const ehdr, t += (_align & -t); /* word-byte align */ new_e_shoff = t; + set_shnum(ehdr, shdr0, new_shnum); + /* body for new shstrtab */ if (ulseek(sb.st_size, SEEK_SET) < 0) return -1; @@ -255,7 +335,6 @@ static int append_func(Elf_Ehdr *const ehdr, return -1; ehdr->e_shoff = _w(new_e_shoff); - ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum)); /* {.rel,}__mcount_loc */ if (ulseek(0, SEEK_SET) < 0) return -1; if (uwrite(ehdr, sizeof(*ehdr)) < 0) @@ -434,6 +513,8 @@ static int find_secsym_ndx(unsigned const txtndx, uint_t *const recvalp, unsigned int *sym_index, Elf_Shdr const *const symhdr, + Elf32_Word const *symtab, + Elf32_Word const *symtab_shndx, Elf_Ehdr const *const ehdr) { Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset) @@ -445,7 +526,7 @@ static int find_secsym_ndx(unsigned const txtndx, for (symp = sym0, t = nsym; t; --t, ++symp) { unsigned int const st_bind = ELF_ST_BIND(symp->st_info); - if (txtndx == w2(symp->st_shndx) + if (txtndx == get_symindex(symp, symtab, symtab_shndx) /* avoid STB_WEAK */ && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) { /* function symbols on ARM have quirks, avoid them */ @@ -516,21 +597,23 @@ static unsigned tot_relsize(Elf_Shdr const *const shdr0, return totrelsz; } - /* Overall supervision for Elf32 ET_REL file. */ static int do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype) { Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff) + (void *)ehdr); - unsigned const nhdr = w2(ehdr->e_shnum); - Elf_Shdr *const shstr = &shdr0[w2(ehdr->e_shstrndx)]; + unsigned const nhdr = get_shnum(ehdr, shdr0); + Elf_Shdr *const shstr = &shdr0[get_shstrndx(ehdr, shdr0)]; char const *const shstrtab = (char const *)(_w(shstr->sh_offset) + (void *)ehdr); Elf_Shdr const *relhdr; unsigned k; + Elf32_Word *symtab; + Elf32_Word *symtab_shndx; + /* Upper bound on space: assume all relevant relocs are for mcount. */ unsigned totrelsz; @@ -561,6 +644,8 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname, return -1; } + find_symtab(ehdr, shdr0, nhdr, &symtab, &symtab_shndx); + for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) { char const *const txtname = has_rel_mcount(relhdr, shdr0, shstrtab, fname); @@ -577,6 +662,7 @@ static int do_func(Elf_Ehdr *const ehdr, char const *const fname, result = find_secsym_ndx(w(relhdr->sh_info), txtname, &recval, &recsym, &shdr0[symsec_sh_link], + symtab, symtab_shndx, ehdr); if (result) goto out; base-commit: b4f633221f0aeac102e463a4be46a643b2e3b819 -- 2.26.2.303.gf8c07b1a785-goog