xref: /openbmc/u-boot/tools/binman/elf_test.py (revision b2b0df8f)
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
13b50e5611SSimon Glass
14b50e5611SSimon Glassbinman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
1519790632SSimon Glass
1619790632SSimon Glass
1719790632SSimon Glassclass FakeEntry:
18*b2b0df8fSSimon Glass    """A fake Entry object, usedfor testing
19*b2b0df8fSSimon Glass
20*b2b0df8fSSimon Glass    This supports an entry with a given size.
21*b2b0df8fSSimon Glass    """
2219790632SSimon Glass    def __init__(self, contents_size):
2319790632SSimon Glass        self.contents_size = contents_size
2419790632SSimon Glass        self.data = 'a' * contents_size
2519790632SSimon Glass
2619790632SSimon Glass    def GetPath(self):
2719790632SSimon Glass        return 'entry_path'
2819790632SSimon Glass
29*b2b0df8fSSimon Glass
30f55382b5SSimon Glassclass FakeSection:
31*b2b0df8fSSimon Glass    """A fake Section object, used for testing
32*b2b0df8fSSimon Glass
33*b2b0df8fSSimon Glass    This has the minimum feature set needed to support testing elf functions.
34*b2b0df8fSSimon Glass    A LookupSymbol() function is provided which returns a fake value for amu
35*b2b0df8fSSimon Glass    symbol requested.
36*b2b0df8fSSimon Glass    """
3719790632SSimon Glass    def __init__(self, sym_value=1):
3819790632SSimon Glass        self.sym_value = sym_value
3919790632SSimon Glass
4019790632SSimon Glass    def GetPath(self):
41f55382b5SSimon Glass        return 'section_path'
4219790632SSimon Glass
4319790632SSimon Glass    def LookupSymbol(self, name, weak, msg):
44*b2b0df8fSSimon Glass        """Fake implementation which returns the same value for all symbols"""
4519790632SSimon Glass        return self.sym_value
46b50e5611SSimon Glass
47*b2b0df8fSSimon Glass
48b50e5611SSimon Glassclass TestElf(unittest.TestCase):
49b50e5611SSimon Glass    def testAllSymbols(self):
50*b2b0df8fSSimon Glass        """Test that we can obtain a symbol from the ELF file"""
5119790632SSimon Glass        fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
52b50e5611SSimon Glass        syms = elf.GetSymbols(fname, [])
53b50e5611SSimon Glass        self.assertIn('.ucode', syms)
54b50e5611SSimon Glass
55b50e5611SSimon Glass    def testRegexSymbols(self):
56*b2b0df8fSSimon Glass        """Test that we can obtain from the ELF file by regular expression"""
5719790632SSimon Glass        fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
58b50e5611SSimon Glass        syms = elf.GetSymbols(fname, ['ucode'])
59b50e5611SSimon Glass        self.assertIn('.ucode', syms)
60b50e5611SSimon Glass        syms = elf.GetSymbols(fname, ['missing'])
61b50e5611SSimon Glass        self.assertNotIn('.ucode', syms)
62b50e5611SSimon Glass        syms = elf.GetSymbols(fname, ['missing', 'ucode'])
63b50e5611SSimon Glass        self.assertIn('.ucode', syms)
64b50e5611SSimon Glass
6519790632SSimon Glass    def testMissingFile(self):
66*b2b0df8fSSimon Glass        """Test that a missing file is detected"""
6719790632SSimon Glass        entry = FakeEntry(10)
68f55382b5SSimon Glass        section = FakeSection()
6919790632SSimon Glass        with self.assertRaises(ValueError) as e:
70f55382b5SSimon Glass            syms = elf.LookupAndWriteSymbols('missing-file', entry, section)
7119790632SSimon Glass        self.assertIn("Filename 'missing-file' not found in input path",
7219790632SSimon Glass                      str(e.exception))
7319790632SSimon Glass
7419790632SSimon Glass    def testOutsideFile(self):
75*b2b0df8fSSimon Glass        """Test a symbol which extends outside the entry area is detected"""
7619790632SSimon Glass        entry = FakeEntry(10)
77f55382b5SSimon Glass        section = FakeSection()
7819790632SSimon Glass        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
7919790632SSimon Glass        with self.assertRaises(ValueError) as e:
80f55382b5SSimon Glass            syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
8119790632SSimon Glass        self.assertIn('entry_path has offset 4 (size 8) but the contents size '
8219790632SSimon Glass                      'is a', str(e.exception))
8319790632SSimon Glass
8419790632SSimon Glass    def testMissingImageStart(self):
85*b2b0df8fSSimon Glass        """Test that we detect a missing __image_copy_start symbol
86*b2b0df8fSSimon Glass
87*b2b0df8fSSimon Glass        This is needed to mark the start of the image. Without it we cannot
88*b2b0df8fSSimon Glass        locate the offset of a binman symbol within the image.
89*b2b0df8fSSimon Glass        """
9019790632SSimon Glass        entry = FakeEntry(10)
91f55382b5SSimon Glass        section = FakeSection()
9219790632SSimon Glass        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_bad')
93f55382b5SSimon Glass        self.assertEqual(elf.LookupAndWriteSymbols(elf_fname, entry, section),
9419790632SSimon Glass                         None)
9519790632SSimon Glass
9619790632SSimon Glass    def testBadSymbolSize(self):
97*b2b0df8fSSimon Glass        """Test that an attempt to use an 8-bit symbol are detected
98*b2b0df8fSSimon Glass
99*b2b0df8fSSimon Glass        Only 32 and 64 bits are supported, since we need to store an offset
100*b2b0df8fSSimon Glass        into the image.
101*b2b0df8fSSimon Glass        """
10219790632SSimon Glass        entry = FakeEntry(10)
103f55382b5SSimon Glass        section = FakeSection()
10419790632SSimon Glass        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_size')
10519790632SSimon Glass        with self.assertRaises(ValueError) as e:
106f55382b5SSimon Glass            syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
10719790632SSimon Glass        self.assertIn('has size 1: only 4 and 8 are supported',
10819790632SSimon Glass                      str(e.exception))
10919790632SSimon Glass
11019790632SSimon Glass    def testNoValue(self):
111*b2b0df8fSSimon Glass        """Test the case where we have no value for the symbol
112*b2b0df8fSSimon Glass
113*b2b0df8fSSimon Glass        This should produce -1 values for all thress symbols, taking up the
114*b2b0df8fSSimon Glass        first 16 bytes of the image.
115*b2b0df8fSSimon Glass        """
11619790632SSimon Glass        entry = FakeEntry(20)
117f55382b5SSimon Glass        section = FakeSection(sym_value=None)
11819790632SSimon Glass        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
119f55382b5SSimon Glass        syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
12019790632SSimon Glass        self.assertEqual(chr(255) * 16 + 'a' * 4, entry.data)
12119790632SSimon Glass
12219790632SSimon Glass    def testDebug(self):
123*b2b0df8fSSimon Glass        """Check that enabling debug in the elf module produced debug output"""
12419790632SSimon Glass        elf.debug = True
12519790632SSimon Glass        entry = FakeEntry(20)
126f55382b5SSimon Glass        section = FakeSection()
12719790632SSimon Glass        elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
128c3f94541SSimon Glass        with test_util.capture_sys_output() as (stdout, stderr):
129f55382b5SSimon Glass            syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
13019790632SSimon Glass        elf.debug = False
13119790632SSimon Glass        self.assertTrue(len(stdout.getvalue()) > 0)
13219790632SSimon Glass
13319790632SSimon Glass
134b50e5611SSimon Glassif __name__ == '__main__':
135b50e5611SSimon Glass    unittest.main()
136