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