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 6057EC433F5 for ; Tue, 15 Feb 2022 11:53:45 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6400383A48; Tue, 15 Feb 2022 12:53:33 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="TwGPCMOj"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id ED925836A8; Tue, 15 Feb 2022 12:53:25 +0100 (CET) Received: from mail-ej1-x636.google.com (mail-ej1-x636.google.com [IPv6:2a00:1450:4864:20::636]) (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 0D12183A3B for ; Tue, 15 Feb 2022 12:53:19 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=alpernebiyasak@gmail.com Received: by mail-ej1-x636.google.com with SMTP id k25so43664204ejp.5 for ; Tue, 15 Feb 2022 03:53:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:date:mime-version:user-agent:from:subject:to:cc :references:content-language:in-reply-to:content-transfer-encoding; bh=OFSX8ZRZFQ8GRuTOF3pvO5E3BWyQjYvFgkApi8bnI8k=; b=TwGPCMOjRqgAfdsDRw+9QqqVkBcGY5azOFGUHsyvLWXPVKY/wmmZR8KVs70XJIRwpK +tWgXi3Q52Nd/66S8pQaIqaINp/zbZvWtzoAx0qeZ8zKSTxSjWiU0XHyiZqmwGawOdZM wQ/4pmd25hN93BgEAyKVxI/BPUKmi7pUe7hDCgtDjajixB1rXi3WM3qdegZwl4Zqzo6t x9JT8gM7IFm7f+SuSUo+Pcc58z/i6ICQyOcvd9a9VhyzYPxiV5pXMtFZMF1rksG3v0fO Il1zHjOouP0r5qqUggP6zwWX+dwBJz6Df7SBMF9hL1xS6IA3zs7GM/xwku1tdXIfFZA8 /PFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:from :subject:to:cc:references:content-language:in-reply-to :content-transfer-encoding; bh=OFSX8ZRZFQ8GRuTOF3pvO5E3BWyQjYvFgkApi8bnI8k=; b=kkf/DHlVNKWmuge8MFkWYkcrwuLnIJdf058QUz74TPy0TCDJO/Jb4gW5v/JpHqBe9A JiyKe37s5KXb+GiGnsRmbA1gKnnl3Pga9hxknvEEWpgdYd8fvMF2d1jwlKo7E3w68c9+ cXEfpahNJiTjUMX8WtNzJ4VBeCS3wwO0IrmQ8wyH9nrWmS5ZoX5SED1bo1AxIxA1tIdY /Ecd9UwFILP55rzhsRTd8IP5KUcMFez//FPwqcgJbvH1lTa2ABHQwQz71tKaEeeJLO40 g0HVwRq2y2IQTcn7FyvaTf5ovE6HoM6/FWB5OWcx6t9CWnc0dRLNxxy2jbIhGtEE7m2J M/Cw== X-Gm-Message-State: AOAM530h5UEpnWuhYLoZiYaPNRCHQryKQIwrPvrEdgh0nGX/4EWtfy0s QPb0GhUfBbgZ7iXhEO+KQcM= X-Google-Smtp-Source: ABdhPJz69e+bsrYdkLHx5Q4Q2GjXwVVefsK5FHUxnBSQuk+b31eYrZGjxFWpHpR0/87wTOV49kxMNg== X-Received: by 2002:a17:906:b152:: with SMTP id bt18mr2689826ejb.584.1644925998661; Tue, 15 Feb 2022 03:53:18 -0800 (PST) Received: from [192.168.0.74] ([178.233.26.119]) by smtp.gmail.com with ESMTPSA id d21sm2324115eja.15.2022.02.15.03.53.16 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 15 Feb 2022 03:53:18 -0800 (PST) Message-ID: <9854f0a5-18e6-71c2-e60a-80280b736d76@gmail.com> Date: Tue, 15 Feb 2022 14:44:19 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux aarch64; rv:91.0) Gecko/20100101 Thunderbird/91.6.0 From: Alper Nebi Yasak Subject: Re: [PATCH 11/24] elf: Add a way to read segment information from an ELF file To: Simon Glass , U-Boot Mailing List Cc: huang lin , Jeffy Chen , Kever Yang , Tom Rini , Philippe Reynes , Ivan Mikhaylov References: <20220208185008.35843-1-sjg@chromium.org> <20220208185008.35843-10-sjg@chromium.org> Content-Language: en-US In-Reply-To: <20220208185008.35843-10-sjg@chromium.org> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit 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.5 at phobos.denx.de X-Virus-Status: Clean On 08/02/2022 21:49, Simon Glass wrote: > Add a function which reads the segments and the entry address. > > Also fix a comment nit in the tests while we are here. > > Signed-off-by: Simon Glass > --- > > tools/binman/elf.py | 37 +++++++++++++++++++++++++++++++++++++ > tools/binman/elf_test.py | 31 +++++++++++++++++++++++++++++-- > 2 files changed, 66 insertions(+), 2 deletions(-) > > diff --git a/tools/binman/elf.py b/tools/binman/elf.py > index de2bb4651f..2b83ac1876 100644 > --- a/tools/binman/elf.py > +++ b/tools/binman/elf.py > @@ -20,6 +20,7 @@ from patman import tout > ELF_TOOLS = True > try: > from elftools.elf.elffile import ELFFile > + from elftools.elf.elffile import ELFError > from elftools.elf.sections import SymbolTableSection > except: # pragma: no cover > ELF_TOOLS = False > @@ -369,3 +370,39 @@ def UpdateFile(infile, outfile, start_sym, end_sym, insert): > newdata += data[syms[end_sym].offset:] > tools.WriteFile(outfile, newdata) > tout.Info('Written to offset %#x' % syms[start_sym].offset) > + > +def read_segments(data): > + """Read segments from an ELF file > + > + Args: > + data (bytes): Contents of file > + > + Returns: > + tuple: > + list of segments, each: > + int: Segment number (0 = first) > + int: Start address of segment in memory > + bytes: Contents of segment > + int: entry address for image > + > + Raises: > + ValueError: elftools is not available ... or input data is not a correct ELF file? > + """ > + if not ELF_TOOLS: > + raise ValueError('Python elftools package is not available') I see something like ModuleNotFoundError("No module named 'elftools'") when I try to import an unavailable module, so maybe this could match that. > + with io.BytesIO(data) as inf: > + try: > + elf = ELFFile(inf) > + except ELFError as err: > + raise ValueError(err) Could also be: raise ValueError("Not an ELF file") from err But I guess you want err's message here to match on it in tests. (It's also possible but slightly inconvenient with __cause__ when using raise-from) > + entry = elf.header['e_entry'] > + segments = [] > + for i in range(elf.num_segments()): > + segment = elf.get_segment(i) > + if segment['p_type'] != 'PT_LOAD' or not segment['p_memsz']: I can't say I fully understand ELF details, is it obvious in context that a function named read_segments() would only return these segments, or should the name be explicit about it e.g. read_loadable_segments()? > + skipped = 1 # To make code-coverage see this line > + continue > + start = segment['p_offset'] > + rend = start + segment['p_filesz'] > + segments.append((i, segment['p_paddr'], data[start:rend])) > + return segments, entry > diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py > index f727258487..369260c17a 100644 > --- a/tools/binman/elf_test.py > +++ b/tools/binman/elf_test.py > @@ -56,8 +56,8 @@ class FakeSection: > def BuildElfTestFiles(target_dir): > """Build ELF files used for testing in binman > > - This compiles and links the test files into the specified directory. It the > - Makefile and source files in the binman test/ directory. > + This compiles and links the test files into the specified directory. It uses > + the Makefile and source files in the binman test/ directory. > > Args: > target_dir: Directory to put the files into > @@ -258,6 +258,33 @@ class TestElf(unittest.TestCase): > offset = elf.GetSymbolFileOffset(fname, ['missing_sym']) > self.assertEqual({}, offset) > > + def test_read_segments(self): > + """Test for read_segments()""" > + if not elf.ELF_TOOLS: > + self.skipTest('Python elftools not available') > + fname = self.ElfTestFile('embed_data') > + segments, entry = elf.read_segments(tools.ReadFile(fname)) > + > + def test_read_segments_fail(self): > + """Test for read_segments() without elftools""" > + try: > + old_val = elf.ELF_TOOLS > + elf.ELF_TOOLS = False > + fname = self.ElfTestFile('embed_data') > + with self.assertRaises(ValueError) as e: > + elf.read_segments(tools.ReadFile(fname)) > + self.assertIn('Python elftools package is not available', > + str(e.exception)) > + finally: > + elf.ELF_TOOLS = old_val > + > + def test_read_segments_bad_data(self): > + """Test for read_segments() with an invalid ELF file""" > + fname = self.ElfTestFile('embed_data') > + with self.assertRaises(ValueError) as e: > + elf.read_segments(tools.GetBytes(100, 100)) > + self.assertIn('Magic number does not match', str(e.exception)) > + > > if __name__ == '__main__': > unittest.main()