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