xref: /openbmc/u-boot/tools/binman/elf_test.py (revision cf033e04)
183d290c5STom Rini# SPDX-License-Identifier: GPL-2.0+
2b50e5611SSimon Glass# Copyright (c) 2017 Google, Inc
3b50e5611SSimon Glass# Written by Simon Glass <sjg@chromium.org>
4b50e5611SSimon Glass#
5b50e5611SSimon Glass# Test for the elf module
6b50e5611SSimon Glass
7b50e5611SSimon Glassimport os
8b50e5611SSimon Glassimport sys
9b50e5611SSimon Glassimport unittest
10b50e5611SSimon Glass
11b50e5611SSimon Glassimport elf
12c3f94541SSimon Glassimport test_util
13*e0e6275fSSimon Glassimport tools
14b50e5611SSimon Glass
15b50e5611SSimon Glassbinman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
1619790632SSimon Glass
1719790632SSimon Glass
1819790632SSimon Glassclass FakeEntry:
19b2b0df8fSSimon Glass    """A fake Entry object, usedfor testing
20b2b0df8fSSimon Glass
21b2b0df8fSSimon Glass    This supports an entry with a given size.
22b2b0df8fSSimon Glass    """
2319790632SSimon Glass    def __init__(self, contents_size):
2419790632SSimon Glass        self.contents_size = contents_size
2519790632SSimon Glass        self.data = 'a' * contents_size
2619790632SSimon Glass
2719790632SSimon Glass    def GetPath(self):
2819790632SSimon Glass        return 'entry_path'
2919790632SSimon Glass
30b2b0df8fSSimon Glass
31f55382b5SSimon Glassclass FakeSection:
32b2b0df8fSSimon Glass    """A fake Section object, used for testing
33b2b0df8fSSimon Glass
34b2b0df8fSSimon Glass    This has the minimum feature set needed to support testing elf functions.
35b2b0df8fSSimon Glass    A LookupSymbol() function is provided which returns a fake value for amu
36b2b0df8fSSimon Glass    symbol requested.
37b2b0df8fSSimon Glass    """
3819790632SSimon Glass    def __init__(self, sym_value=1):
3919790632SSimon Glass        self.sym_value = sym_value
4019790632SSimon Glass
4119790632SSimon Glass    def GetPath(self):
42f55382b5SSimon Glass        return 'section_path'
4319790632SSimon Glass
4419790632SSimon Glass    def LookupSymbol(self, name, weak, msg):
45b2b0df8fSSimon Glass        """Fake implementation which returns the same value for all symbols"""
4619790632SSimon Glass        return self.sym_value
47b50e5611SSimon Glass
48b2b0df8fSSimon Glass
49b50e5611SSimon Glassclass TestElf(unittest.TestCase):
50*e0e6275fSSimon Glass    @classmethod
51*e0e6275fSSimon Glass    def setUpClass(self):
52*e0e6275fSSimon Glass        tools.SetInputDirs(['.'])
53*e0e6275fSSimon Glass
54b50e5611SSimon Glass    def testAllSymbols(self):
55b2b0df8fSSimon Glass        """Test that we can obtain a symbol from the ELF file"""
5619790632SSimon Glass        fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
57b50e5611SSimon Glass        syms = elf.GetSymbols(fname, [])
58b50e5611SSimon Glass        self.assertIn('.ucode', syms)
59b50e5611SSimon Glass
60b50e5611SSimon Glass    def testRegexSymbols(self):
61b2b0df8fSSimon Glass        """Test that we can obtain from the ELF file by regular expression"""
6219790632SSimon Glass        fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
63b50e5611SSimon Glass        syms = elf.GetSymbols(fname, ['ucode'])
64b50e5611SSimon Glass        self.assertIn('.ucode', syms)
65b50e5611SSimon Glass        syms = elf.GetSymbols(fname, ['missing'])
66b50e5611SSimon Glass        self.assertNotIn('.ucode', syms)
67b50e5611SSimon Glass        syms = elf.GetSymbols(fname, ['missing', 'ucode'])
68b50e5611SSimon Glass        self.assertIn('.ucode', syms)
69b50e5611SSimon Glass
7019790632SSimon Glass    def testMissingFile(self):
71b2b0df8fSSimon Glass        """Test that a missing file is detected"""
7219790632SSimon Glass        entry = FakeEntry(10)
73f55382b5SSimon Glass        section = FakeSection()
7419790632SSimon Glass        with self.assertRaises(ValueError) as e:
75f55382b5SSimon Glass            syms = elf.LookupAndWriteSymbols('missing-file', entry, section)
7619790632SSimon Glass        self.assertIn("Filename 'missing-file' not found in input path",
7719790632SSimon Glass                      str(e.exception))
7819790632SSimon Glass
7919790632SSimon Glass    def testOutsideFile(self):
80b2b0df8fSSimon Glass        """Test a symbol which extends outside the entry area is detected"""
8119790632SSimon Glass        entry = FakeEntry(10)
82f55382b5SSimon Glass        section = FakeSection()
8319790632SSimon Glass        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
8419790632SSimon Glass        with self.assertRaises(ValueError) as e:
85f55382b5SSimon Glass            syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
8619790632SSimon Glass        self.assertIn('entry_path has offset 4 (size 8) but the contents size '
8719790632SSimon Glass                      'is a', str(e.exception))
8819790632SSimon Glass
8919790632SSimon Glass    def testMissingImageStart(self):
90b2b0df8fSSimon Glass        """Test that we detect a missing __image_copy_start symbol
91b2b0df8fSSimon Glass
92b2b0df8fSSimon Glass        This is needed to mark the start of the image. Without it we cannot
93b2b0df8fSSimon Glass        locate the offset of a binman symbol within the image.
94b2b0df8fSSimon Glass        """
9519790632SSimon Glass        entry = FakeEntry(10)
96f55382b5SSimon Glass        section = FakeSection()
9719790632SSimon Glass        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_bad')
98f55382b5SSimon Glass        self.assertEqual(elf.LookupAndWriteSymbols(elf_fname, entry, section),
9919790632SSimon Glass                         None)
10019790632SSimon Glass
10119790632SSimon Glass    def testBadSymbolSize(self):
102b2b0df8fSSimon Glass        """Test that an attempt to use an 8-bit symbol are detected
103b2b0df8fSSimon Glass
104b2b0df8fSSimon Glass        Only 32 and 64 bits are supported, since we need to store an offset
105b2b0df8fSSimon Glass        into the image.
106b2b0df8fSSimon Glass        """
10719790632SSimon Glass        entry = FakeEntry(10)
108f55382b5SSimon Glass        section = FakeSection()
10919790632SSimon Glass        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_size')
11019790632SSimon Glass        with self.assertRaises(ValueError) as e:
111f55382b5SSimon Glass            syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
11219790632SSimon Glass        self.assertIn('has size 1: only 4 and 8 are supported',
11319790632SSimon Glass                      str(e.exception))
11419790632SSimon Glass
11519790632SSimon Glass    def testNoValue(self):
116b2b0df8fSSimon Glass        """Test the case where we have no value for the symbol
117b2b0df8fSSimon Glass
118b2b0df8fSSimon Glass        This should produce -1 values for all thress symbols, taking up the
119b2b0df8fSSimon Glass        first 16 bytes of the image.
120b2b0df8fSSimon Glass        """
12119790632SSimon Glass        entry = FakeEntry(20)
122f55382b5SSimon Glass        section = FakeSection(sym_value=None)
12319790632SSimon Glass        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
124f55382b5SSimon Glass        syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
12519790632SSimon Glass        self.assertEqual(chr(255) * 16 + 'a' * 4, entry.data)
12619790632SSimon Glass
12719790632SSimon Glass    def testDebug(self):
128b2b0df8fSSimon Glass        """Check that enabling debug in the elf module produced debug output"""
12919790632SSimon Glass        elf.debug = True
13019790632SSimon Glass        entry = FakeEntry(20)
131f55382b5SSimon Glass        section = FakeSection()
13219790632SSimon Glass        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
133c3f94541SSimon Glass        with test_util.capture_sys_output() as (stdout, stderr):
134f55382b5SSimon Glass            syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
13519790632SSimon Glass        elf.debug = False
13619790632SSimon Glass        self.assertTrue(len(stdout.getvalue()) > 0)
13719790632SSimon Glass
13819790632SSimon Glass
139b50e5611SSimon Glassif __name__ == '__main__':
140b50e5611SSimon Glass    unittest.main()
141