From patchwork Tue Nov 14 01:54:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 837652 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="tAhmI0Yx"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3ybVxc3vMZz9s7G for ; Tue, 14 Nov 2017 12:57:08 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id D0AF3C21EBF; Tue, 14 Nov 2017 01:55:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id CAF33C21E5D; Tue, 14 Nov 2017 01:55:16 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D5A49C21D76; Tue, 14 Nov 2017 01:55:13 +0000 (UTC) Received: from mail-ot0-f176.google.com (mail-ot0-f176.google.com [74.125.82.176]) by lists.denx.de (Postfix) with ESMTPS id E9B85C21D80 for ; Tue, 14 Nov 2017 01:55:12 +0000 (UTC) Received: by mail-ot0-f176.google.com with SMTP id s4so6171924ote.4 for ; Mon, 13 Nov 2017 17:55:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=gColAhZktFUahbfT+SEInpLhVRJYdKkFfGezVFQAfu8=; b=tAhmI0YxqFJHf9HM7kW/mCuTp3W2bzqhIwWwTQ1cooR9ShAlNe86hmEKSrcMtp1LYX WbidjRXQbJQ428YMKoaEmUZYekuG7wGxDrd3S98x1Hm1VqXyyGNZCf6SkT5l8yEbgAQ5 CY1bcm9a+N4rzneaje9yzGp0smugXMIpkCYj5AvnyKcXmvY5BH0ipa3rya4LQgNgl5T0 xBUS0mTWAhtqJGqSNUBezUg7m0ssW57hZAbTUsSWPbxwJdJP/LnMr/dqAS3vku53k7CU LGS3cNPN73Xuq7mVLB6ZQ5PsoNV4/oAxjlUB3wrOrndGvgby7a/AbWev41aY+nnaeHCb ErkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=gColAhZktFUahbfT+SEInpLhVRJYdKkFfGezVFQAfu8=; b=nQ2UmSDIdvRwJSnJUBwHo1JcrlWTJ1F4V8knI0LU1DugP9tgEYeY3lCylKtaQR7R85 FLJGpu5K9oUKY57FKVCzpYmOqJXf1FvQRyJt+Y57E25hdDBbR12oDaPB+debff3dXeRb janE3zzWa4BT6V/+aACWz59MuRWT5hwp8VaCTFXq2AkhxmF5cVNd8A+lTdiVfz0exn+g EzdQtIYx/dj3hRV3TizbcXwgC8/2nzhv8eKLE9MabMNCZ6BsYLrpfVqT4pZ+A7KZc9LH PIxO7YR4e7lAxr2olOVkWQnc1hzeHn9Ys3RPq/JNdYbOp8YMbiJp7bx0/P4RhSP0QVoE JeRw== X-Gm-Message-State: AJaThX7r2cBkDdKJID08x0yqYwsjwcikSYZnf7mpi1v++5Q6bEaWNRYh HAdbMvDqSX0fVD01fpPZ2KTW9g== X-Google-Smtp-Source: AGs4zMba0p//dFsqpxMYK3F9aigGcgWAZ1y0FlY0w5fzF9OZ08Cxc1TkmU1FYw5380DfrAwGzLqmFg== X-Received: by 10.157.33.228 with SMTP id s91mr6922168otb.0.1510624511231; Mon, 13 Nov 2017 17:55:11 -0800 (PST) Received: from kiwi.bld.corp.google.com ([2620:0:10f2:0:a538:8f87:e149:5b6]) by smtp.gmail.com with ESMTPSA id j40sm8478108otj.57.2017.11.13.17.55.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 13 Nov 2017 17:55:10 -0800 (PST) Received: by kiwi.bld.corp.google.com (Postfix, from userid 121222) id D5468141AE7; Mon, 13 Nov 2017 18:55:09 -0700 (MST) From: Simon Glass To: U-Boot Mailing List Date: Mon, 13 Nov 2017 18:54:54 -0700 Message-Id: <20171114015506.25673-2-sjg@chromium.org> X-Mailer: git-send-email 2.15.0.448.gf294e3d99a-goog In-Reply-To: <20171114015506.25673-1-sjg@chromium.org> References: <20171114015506.25673-1-sjg@chromium.org> Cc: Tom Rini Subject: [U-Boot] [PATCH 01/13] binman: Add a function to read ELF symbols X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" In some cases we need to read symbols from U-Boot. At present we have a a few cases which does this via 'nm' and 'grep'. It is better to use objdump since that tells us the size of the symbols and also whether it is weak or not. Add a new module which reads ELF information from files. Update existing uses of 'nm' to use this module. Signed-off-by: Simon Glass Signed-off-by: Simon Glass --- tools/binman/binman.py | 3 +- tools/binman/elf.py | 77 +++++++++++++++++++++++++++++ tools/binman/elf_test.py | 32 ++++++++++++ tools/binman/etype/u_boot_spl_bss_pad.py | 7 +-- tools/binman/etype/u_boot_with_ucode_ptr.py | 9 ++-- tools/binman/ftest.py | 7 +++ tools/binman/test/bss_data.c | 2 +- tools/binman/test/u_boot_ucode_ptr.c | 2 +- 8 files changed, 128 insertions(+), 11 deletions(-) create mode 100644 tools/binman/elf.py create mode 100644 tools/binman/elf_test.py diff --git a/tools/binman/binman.py b/tools/binman/binman.py index 3ccf25f1f88..81a613ddc40 100755 --- a/tools/binman/binman.py +++ b/tools/binman/binman.py @@ -33,6 +33,7 @@ import control def RunTests(): """Run the functional tests and any embedded doctests""" + import elf_test import entry_test import fdt_test import ftest @@ -50,7 +51,7 @@ def RunTests(): # 'entry' module. suite = unittest.TestLoader().loadTestsFromTestCase(entry_test.TestEntry) suite.run(result) - for module in (ftest.TestFunctional, fdt_test.TestFdt): + for module in (ftest.TestFunctional, fdt_test.TestFdt, elf_test.TestElf): suite = unittest.TestLoader().loadTestsFromTestCase(module) suite.run(result) diff --git a/tools/binman/elf.py b/tools/binman/elf.py new file mode 100644 index 00000000000..97208b17950 --- /dev/null +++ b/tools/binman/elf.py @@ -0,0 +1,77 @@ +# Copyright (c) 2016 Google, Inc +# Written by Simon Glass +# +# SPDX-License-Identifier: GPL-2.0+ +# +# Handle various things related to ELF images +# + +from collections import namedtuple, OrderedDict +import command +import os +import re +import struct + +import tools + +Symbol = namedtuple('Symbol', ['section', 'address', 'size', 'weak']) + +# Used for tests which don't have an ELF file to read +ignore_missing_files = False + + +def GetSymbols(fname, patterns): + """Get the symbols from an ELF file + + Args: + fname: Filename of the ELF file to read + patterns: List of regex patterns to search for, each a string + + Returns: + None, if the file does not exist, or Dict: + key: Name of symbol + value: Hex value of symbol + """ + stdout = command.Output('objdump', '-t', fname, raise_on_error=False) + lines = stdout.splitlines() + if patterns: + re_syms = re.compile('|'.join(patterns)) + else: + re_syms = None + syms = {} + syms_started = False + for line in lines: + if not line or not syms_started: + if 'SYMBOL TABLE' in line: + syms_started = True + line = None # Otherwise code coverage complains about 'continue' + continue + if re_syms and not re_syms.search(line): + continue + + space_pos = line.find(' ') + value, rest = line[:space_pos], line[space_pos + 1:] + flags = rest[:7] + parts = rest[7:].split() + section, size = parts[:2] + if len(parts) > 2: + name = parts[2] + syms[name] = Symbol(section, int(value, 16), int(size,16), + flags[1] == 'w') + return syms + +def GetSymbolAddress(fname, sym_name): + """Get a value of a symbol from an ELF file + + Args: + fname: Filename of the ELF file to read + patterns: List of regex patterns to search for, each a string + + Returns: + Symbol value (as an integer) or None if not found + """ + syms = GetSymbols(fname, [sym_name]) + sym = syms.get(sym_name) + if not sym: + return None + return sym.address diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py new file mode 100644 index 00000000000..dca7bc59f99 --- /dev/null +++ b/tools/binman/elf_test.py @@ -0,0 +1,32 @@ +# +# Copyright (c) 2017 Google, Inc +# Written by Simon Glass +# +# SPDX-License-Identifier: GPL-2.0+ +# +# Test for the elf module + +import os +import sys +import unittest + +import elf + +binman_dir = os.path.dirname(os.path.realpath(sys.argv[0])) +fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr') + +class TestElf(unittest.TestCase): + def testAllSymbols(self): + syms = elf.GetSymbols(fname, []) + self.assertIn('.ucode', syms) + + def testRegexSymbols(self): + syms = elf.GetSymbols(fname, ['ucode']) + self.assertIn('.ucode', syms) + syms = elf.GetSymbols(fname, ['missing']) + self.assertNotIn('.ucode', syms) + syms = elf.GetSymbols(fname, ['missing', 'ucode']) + self.assertIn('.ucode', syms) + +if __name__ == '__main__': + unittest.main() diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py index c005f28191f..c37f61db235 100644 --- a/tools/binman/etype/u_boot_spl_bss_pad.py +++ b/tools/binman/etype/u_boot_spl_bss_pad.py @@ -9,6 +9,7 @@ # import command +import elf from entry import Entry from blob import Entry_blob import tools @@ -19,8 +20,8 @@ class Entry_u_boot_spl_bss_pad(Entry_blob): def ObtainContents(self): fname = tools.GetInputFilename('spl/u-boot-spl') - args = [['nm', fname], ['grep', '__bss_size']] - out = command.RunPipe(args, capture=True).stdout.splitlines() - bss_size = int(out[0].split()[0], 16) + bss_size = elf.GetSymbolAddress(fname, '__bss_size') + if not bss_size: + self.Raise('Expected __bss_size symbol in spl/u-boot-spl') self.data = chr(0) * bss_size self.contents_size = bss_size diff --git a/tools/binman/etype/u_boot_with_ucode_ptr.py b/tools/binman/etype/u_boot_with_ucode_ptr.py index 6f01adb9701..99b437130db 100644 --- a/tools/binman/etype/u_boot_with_ucode_ptr.py +++ b/tools/binman/etype/u_boot_with_ucode_ptr.py @@ -9,6 +9,7 @@ import struct import command +import elf from entry import Entry from blob import Entry_blob import fdt_util @@ -31,11 +32,9 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob): def ObtainContents(self): # Figure out where to put the microcode pointer fname = tools.GetInputFilename(self.elf_fname) - args = [['nm', fname], ['grep', '-w', '_dt_ucode_base_size']] - out = (command.RunPipe(args, capture=True, raise_on_error=False). - stdout.splitlines()) - if len(out) == 1: - self.target_pos = int(out[0].split()[0], 16) + sym = elf.GetSymbolAddress(fname, '_dt_ucode_base_size') + if sym: + self.target_pos = sym elif not fdt_util.GetBool(self._node, 'optional-ucode'): self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 9083143894f..c8155788afc 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -835,6 +835,13 @@ class TestFunctional(unittest.TestCase): data = self._DoReadFile('47_spl_bss_pad.dts') self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data) + with open(self.TestFile('u_boot_ucode_ptr')) as fd: + TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read()) + with self.assertRaises(ValueError) as e: + data = self._DoReadFile('47_spl_bss_pad.dts') + self.assertIn('Expected __bss_size symbol in spl/u-boot-spl', + str(e.exception)) + def testPackStart16Spl(self): """Test that an image with an x86 start16 region can be created""" data = self._DoReadFile('48_x86-start16-spl.dts') diff --git a/tools/binman/test/bss_data.c b/tools/binman/test/bss_data.c index f865a9d9f67..e0305c382c3 100644 --- a/tools/binman/test/bss_data.c +++ b/tools/binman/test/bss_data.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-2.0+ * * Simple program to create a _dt_ucode_base_size symbol which can be read - * by 'nm'. This is used by binman tests. + * by binutils. This is used by binman tests. */ int bss_data[10]; diff --git a/tools/binman/test/u_boot_ucode_ptr.c b/tools/binman/test/u_boot_ucode_ptr.c index 24f349fb9e4..734d54f0d41 100644 --- a/tools/binman/test/u_boot_ucode_ptr.c +++ b/tools/binman/test/u_boot_ucode_ptr.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-2.0+ * * Simple program to create a _dt_ucode_base_size symbol which can be read - * by 'nm'. This is used by binman tests. + * by binutils. This is used by binman tests. */ static unsigned long _dt_ucode_base_size[2]