From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 91DC4C04A95 for ; Sun, 25 Sep 2022 15:05:24 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 7D83584BE1; Sun, 25 Sep 2022 17:03:51 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="eRpQ4XZB"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A49DE84C0E; Sun, 25 Sep 2022 17:03:28 +0200 (CEST) Received: from mail-io1-xd32.google.com (mail-io1-xd32.google.com [IPv6:2607:f8b0:4864:20::d32]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id D4DA684B6B for ; Sun, 25 Sep 2022 17:03:23 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd32.google.com with SMTP id h194so3430216iof.4 for ; Sun, 25 Sep 2022 08:03:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date; bh=GmUqq7jN1OYhCiL/ojJZRe6D0ESVGiRa7k/YntNPHOI=; b=eRpQ4XZBu7XG/a3gLTD9F74mqY0C4BT8YrRAWJPhax77xKkE/gRjmzja5jIaZFpT8D d93kDUNPwgLn3mA5LXvEe9DgmGgEIZ/KU6Qu0BCg3CubynRLxbqBMKtU+2wsg4euZhYP k2g7X+waF1OtJAB4feNb7sA9FXR2Kq+HftuM8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=GmUqq7jN1OYhCiL/ojJZRe6D0ESVGiRa7k/YntNPHOI=; b=O9vXuz9eDBVBa2MdXftOA/WypeGKMgW/akfDqaUOgtuuh0DQrNkvRBI0JpRWYwkpw8 tMIKu9fEPcH/5jzHWtX6i/9ZKtWvNdeGd099gcd32jk+lKzY8qNU8UyXRTQCNiv3SliF DXOBXf8LOwNKwqam7HikNxVCvbBGEl0nFIJpUUrtvKlaBpKCvryA2WF7vmaFtr+bt56m QXEnLXcg/Xb62MQmuIl9HfszvJPV9F6aEuydgA2e2nDWArS4/ESsF2d90O6GJf0DGfhN nyZdNd2hmiSo8oT5TSy2S+JU62EXjlbu4DrHkuyCfBPwJnNP27NutJx2Zk9Dg2qqhegV IAjw== X-Gm-Message-State: ACrzQf1ax789fX4QFcmzmRa4FyDlACPLhuxdkGN+WiPsYFzXctDMRs8C n9wXIyRVNsyHrmkR9o5KN62bhVjOOuAwJw== X-Google-Smtp-Source: AMsMyM4a/Rf0vb0BNtkBHIksE0tdc+cRuxSVozT/N1UvBx4FUXL4QHkOw7ByQNq1XmsVLC6qIiSj2g== X-Received: by 2002:a05:6602:491:b0:672:18ce:8189 with SMTP id y17-20020a056602049100b0067218ce8189mr7843074iov.170.1664118202960; Sun, 25 Sep 2022 08:03:22 -0700 (PDT) Received: from sjg1.roam.corp.google.com (c-67-190-102-125.hsd1.co.comcast.net. [67.190.102.125]) by smtp.gmail.com with ESMTPSA id u19-20020a926013000000b002f19d9838c6sm5360578ilb.25.2022.09.25.08.03.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 25 Sep 2022 08:03:22 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Tom Rini , Simon Glass , Alper Nebi Yasak , Heiko Thiery , Stefan Herbrechtsmeier Subject: [PATCH 13/45] binman: Support writing symbols into ELF files Date: Sun, 25 Sep 2022 09:02:16 -0600 Message-Id: <20220925150248.2524421-14-sjg@chromium.org> X-Mailer: git-send-email 2.37.3.998.g577e59143f-goog In-Reply-To: <20220925150248.2524421-1-sjg@chromium.org> References: <20220925150248.2524421-1-sjg@chromium.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean In some cases we may package the ELF version of SPL builds instead of the binary .bin file. Add support for this. Signed-off-by: Simon Glass --- tools/binman/elf.py | 41 +++++++++++++++---- tools/binman/entry.py | 5 ++- tools/binman/etype/section.py | 2 +- tools/binman/etype/u_boot_spl_elf.py | 3 +- tools/binman/etype/u_boot_tpl_elf.py | 3 +- tools/binman/etype/u_boot_vpl_elf.py | 25 ++++++++++++ tools/binman/ftest.py | 57 +++++++++++++++++++++++++++ tools/binman/test/256_symbols_elf.dts | 27 +++++++++++++ 8 files changed, 151 insertions(+), 12 deletions(-) create mode 100644 tools/binman/etype/u_boot_vpl_elf.py create mode 100644 tools/binman/test/256_symbols_elf.dts diff --git a/tools/binman/elf.py b/tools/binman/elf.py index fec2116880b..fe50bf542c3 100644 --- a/tools/binman/elf.py +++ b/tools/binman/elf.py @@ -210,7 +210,7 @@ def GetPackString(sym, msg): raise ValueError('%s has size %d: only 4 and 8 are supported' % (msg, sym.size)) -def LookupAndWriteSymbols(elf_fname, entry, section): +def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False): """Replace all symbols in an entry with their correct values The entry contents is updated so that values for referenced symbols will be @@ -226,27 +226,52 @@ def LookupAndWriteSymbols(elf_fname, entry, section): """ fname = tools.get_input_filename(elf_fname) syms = GetSymbols(fname, ['image', 'binman']) + if is_elf: + if not ELF_TOOLS: + msg = ("Section '%s': entry '%s'" % + (section.GetPath(), entry.GetPath())) + raise ValueError(f'{msg}: Cannot write symbols to an ELF file without Python elftools') + new_syms = {} + with open(fname, 'rb') as fd: + elf = ELFFile(fd) + for name, sym in syms.items(): + offset = _GetFileOffset(elf, sym.address) + new_syms[name] = Symbol(sym.section, sym.address, sym.size, + sym.weak, offset) + syms = new_syms + if not syms: + tout.debug('LookupAndWriteSymbols: no syms') return base = syms.get('__image_copy_start') - if not base: + if not base and not is_elf: + tout.debug('LookupAndWriteSymbols: no base') return + base_addr = 0 if is_elf else base.address for name, sym in syms.items(): if name.startswith('_binman'): msg = ("Section '%s': Symbol '%s'\n in entry '%s'" % (section.GetPath(), name, entry.GetPath())) - offset = sym.address - base.address - if offset < 0 or offset + sym.size > entry.contents_size: - raise ValueError('%s has offset %x (size %x) but the contents ' - 'size is %x' % (entry.GetPath(), offset, - sym.size, entry.contents_size)) + if is_elf: + # For ELF files, use the file offset + offset = sym.offset + else: + # For blobs use the offset of the symbol, calculated by + # subtracting the base address which by definition is at the + # start + offset = sym.address - base.address + if offset < 0 or offset + sym.size > entry.contents_size: + raise ValueError('%s has offset %x (size %x) but the contents ' + 'size is %x' % (entry.GetPath(), offset, + sym.size, + entry.contents_size)) pack_string = GetPackString(sym, msg) if name == '_binman_sym_magic': value = BINMAN_SYM_MAGIC_VALUE else: # Look up the symbol in our entry tables. value = section.GetImage().LookupImageSymbol(name, sym.weak, - msg, base.address) + msg, base_addr) if value is None: value = -1 pack_string = pack_string.lower() diff --git a/tools/binman/entry.py b/tools/binman/entry.py index bdf53ddd922..1be31a05e00 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -656,7 +656,10 @@ class Entry(object): section: Section containing the entry """ if self.auto_write_symbols: - elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage()) + # Check if we are writing symbols into an ELF file + is_elf = self.GetDefaultFilename() == self.elf_fname + elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage(), + is_elf) def CheckEntries(self): """Check that the entry offsets are correct diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index b68c6fd037b..c56b962c20c 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -550,7 +550,7 @@ class Entry_section(Entry): for name in entries: if name.startswith(root): rest = name[len(root):] - if rest in ['', '-img', '-nodtb']: + if rest in ['', '-elf', '-img', '-nodtb']: entry = entries[name] return entry, entry_name, prop_name diff --git a/tools/binman/etype/u_boot_spl_elf.py b/tools/binman/etype/u_boot_spl_elf.py index 7f1236bcbb3..7b7b4e01495 100644 --- a/tools/binman/etype/u_boot_spl_elf.py +++ b/tools/binman/etype/u_boot_spl_elf.py @@ -18,7 +18,8 @@ class Entry_u_boot_spl_elf(Entry_blob): be relocated to any address for execution. """ def __init__(self, section, etype, node): - super().__init__(section, etype, node) + super().__init__(section, etype, node, auto_write_symbols=True) + self.elf_fname = 'spl/u-boot-spl' def GetDefaultFilename(self): return 'spl/u-boot-spl' diff --git a/tools/binman/etype/u_boot_tpl_elf.py b/tools/binman/etype/u_boot_tpl_elf.py index 3f24d3aa7bc..fd100019b39 100644 --- a/tools/binman/etype/u_boot_tpl_elf.py +++ b/tools/binman/etype/u_boot_tpl_elf.py @@ -18,7 +18,8 @@ class Entry_u_boot_tpl_elf(Entry_blob): be relocated to any address for execution. """ def __init__(self, section, etype, node): - super().__init__(section, etype, node) + super().__init__(section, etype, node, auto_write_symbols=True) + self.elf_fname = 'tpl/u-boot-tpl' def GetDefaultFilename(self): return 'tpl/u-boot-tpl' diff --git a/tools/binman/etype/u_boot_vpl_elf.py b/tools/binman/etype/u_boot_vpl_elf.py new file mode 100644 index 00000000000..2c686790194 --- /dev/null +++ b/tools/binman/etype/u_boot_vpl_elf.py @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2022 Google LLC +# Written by Simon Glass +# +# Entry-type module for U-Boot VPL ELF image +# + +from binman.entry import Entry +from binman.etype.blob import Entry_blob + +class Entry_u_boot_vpl_elf(Entry_blob): + """U-Boot VPL ELF image + + Properties / Entry arguments: + - filename: Filename of VPL u-boot (default 'vpl/u-boot-vpl') + + This is the U-Boot VPL ELF image. It does not include a device tree but can + be relocated to any address for execution. + """ + def __init__(self, section, etype, node): + super().__init__(section, etype, node, auto_write_symbols=True) + self.elf_fname = 'vpl/u-boot-vpl' + + def GetDefaultFilename(self): + return 'vpl/u-boot-vpl' diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 4bdd08046bb..9ae293d918a 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -5965,6 +5965,63 @@ fdt fdtmap Extract the devicetree blob from the fdtmap self.assertIn('Expected __bss_size symbol in vpl/u-boot-vpl', str(e.exception)) + def testSymbolsElf(self): + """Test binman can assign symbols embedded in an ELF file""" + if not elf.ELF_TOOLS: + self.skipTest('Python elftools not available') + self._SetupTplElf('u_boot_binman_syms') + self._SetupVplElf('u_boot_binman_syms') + self._SetupSplElf('u_boot_binman_syms') + data = self._DoReadFileDtb('256_symbols_elf.dts')[0] + image_fname = tools.get_output_filename('image.bin') + + image = control.images['image'] + entries = image.GetEntries() + + for entry in entries.values(): + # No symbols in u-boot and it has faked contents anyway + if entry.name == 'u-boot': + continue + edata = data[entry.image_pos:entry.image_pos + entry.size] + efname = tools.get_output_filename(f'edata-{entry.name}') + tools.write_file(efname, edata) + + syms = elf.GetSymbolFileOffset(efname, ['_binman_u_boot']) + re_name = re.compile('_binman_(u_boot_(.*))_prop_(.*)') + for name, sym in syms.items(): + msg = 'test' + val = elf.GetSymbolValue(sym, edata, msg) + entry_m = re_name.match(name) + if entry_m: + ename, prop = entry_m.group(1), entry_m.group(3) + entry, entry_name, prop_name = image.LookupEntry(entries, + name, msg) + if prop_name == 'offset': + expect_val = entry.offset + elif prop_name == 'image_pos': + expect_val = entry.image_pos + elif prop_name == 'size': + expect_val = entry.size + self.assertEqual(expect_val, val) + + def testSymbolsElfBad(self): + """Check error when trying to write symbols without the elftools lib""" + if not elf.ELF_TOOLS: + self.skipTest('Python elftools not available') + self._SetupTplElf('u_boot_binman_syms') + self._SetupVplElf('u_boot_binman_syms') + self._SetupSplElf('u_boot_binman_syms') + try: + elf.ELF_TOOLS = False + with self.assertRaises(ValueError) as exc: + self._DoReadFileDtb('256_symbols_elf.dts') + finally: + elf.ELF_TOOLS = True + self.assertIn( + "Section '/binman': entry '/binman/u-boot-spl-elf': " + 'Cannot write symbols to an ELF file without Python elftools', + str(exc.exception)) + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/256_symbols_elf.dts b/tools/binman/test/256_symbols_elf.dts new file mode 100644 index 00000000000..0fae118fc12 --- /dev/null +++ b/tools/binman/test/256_symbols_elf.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + pad-byte = <0xff>; + u-boot-spl-elf { + }; + + u-boot { + }; + + u-boot-spl2 { + type = "u-boot-spl-elf"; + }; + + u-boot-tpl-elf { + }; + + u-boot-vpl-elf { + }; + }; +}; -- 2.37.3.998.g577e59143f-goog