1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2017 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
5 # Test for the elf module
18 binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
22 """A fake Entry object, usedfor testing
24 This supports an entry with a given size.
26 def __init__(self, contents_size):
27 self.contents_size = contents_size
28 self.data = tools.GetBytes(ord('a'), contents_size)
35 """A fake Section object, used for testing
37 This has the minimum feature set needed to support testing elf functions.
38 A LookupSymbol() function is provided which returns a fake value for amu
41 def __init__(self, sym_value=1):
42 self.sym_value = sym_value
47 def LookupSymbol(self, name, weak, msg):
48 """Fake implementation which returns the same value for all symbols"""
52 class TestElf(unittest.TestCase):
55 tools.SetInputDirs(['.'])
57 def testAllSymbols(self):
58 """Test that we can obtain a symbol from the ELF file"""
59 fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
60 syms = elf.GetSymbols(fname, [])
61 self.assertIn('.ucode', syms)
63 def testRegexSymbols(self):
64 """Test that we can obtain from the ELF file by regular expression"""
65 fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
66 syms = elf.GetSymbols(fname, ['ucode'])
67 self.assertIn('.ucode', syms)
68 syms = elf.GetSymbols(fname, ['missing'])
69 self.assertNotIn('.ucode', syms)
70 syms = elf.GetSymbols(fname, ['missing', 'ucode'])
71 self.assertIn('.ucode', syms)
73 def testMissingFile(self):
74 """Test that a missing file is detected"""
76 section = FakeSection()
77 with self.assertRaises(ValueError) as e:
78 syms = elf.LookupAndWriteSymbols('missing-file', entry, section)
79 self.assertIn("Filename 'missing-file' not found in input path",
82 def testOutsideFile(self):
83 """Test a symbol which extends outside the entry area is detected"""
85 section = FakeSection()
86 elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
87 with self.assertRaises(ValueError) as e:
88 syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
89 self.assertIn('entry_path has offset 4 (size 8) but the contents size '
90 'is a', str(e.exception))
92 def testMissingImageStart(self):
93 """Test that we detect a missing __image_copy_start symbol
95 This is needed to mark the start of the image. Without it we cannot
96 locate the offset of a binman symbol within the image.
99 section = FakeSection()
100 elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_bad')
101 self.assertEqual(elf.LookupAndWriteSymbols(elf_fname, entry, section),
104 def testBadSymbolSize(self):
105 """Test that an attempt to use an 8-bit symbol are detected
107 Only 32 and 64 bits are supported, since we need to store an offset
110 entry = FakeEntry(10)
111 section = FakeSection()
112 elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_size')
113 with self.assertRaises(ValueError) as e:
114 syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
115 self.assertIn('has size 1: only 4 and 8 are supported',
118 def testNoValue(self):
119 """Test the case where we have no value for the symbol
121 This should produce -1 values for all thress symbols, taking up the
122 first 16 bytes of the image.
124 entry = FakeEntry(20)
125 section = FakeSection(sym_value=None)
126 elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
127 syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
128 self.assertEqual(tools.GetBytes(255, 16) + tools.GetBytes(ord('a'), 4),
132 """Check that enabling debug in the elf module produced debug output"""
134 entry = FakeEntry(20)
135 section = FakeSection()
136 elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
137 with test_util.capture_sys_output() as (stdout, stderr):
138 syms = elf.LookupAndWriteSymbols(elf_fname, entry, section)
140 self.assertTrue(len(stdout.getvalue()) > 0)
142 def testMakeElf(self):
143 """Test for the MakeElf function"""
144 outdir = tempfile.mkdtemp(prefix='elf.')
145 expected_text = b'1234'
146 expected_data = b'wxyz'
147 elf_fname = os.path.join(outdir, 'elf')
148 bin_fname = os.path.join(outdir, 'elf')
150 # Make an Elf file and then convert it to a fkat binary file. This
151 # should produce the original data.
152 elf.MakeElf(elf_fname, expected_text, expected_data)
153 stdout = command.Output('objcopy', '-O', 'binary', elf_fname, bin_fname)
154 with open(bin_fname, 'rb') as fd:
156 self.assertEqual(expected_text + expected_data, data)
157 shutil.rmtree(outdir)
159 def testDecodeElf(self):
160 """Test for the MakeElf function"""
161 if not elf.ELF_TOOLS:
162 self.skipTest('Python elftools not available')
163 outdir = tempfile.mkdtemp(prefix='elf.')
164 expected_text = b'1234'
165 expected_data = b'wxyz'
166 elf_fname = os.path.join(outdir, 'elf')
167 elf.MakeElf(elf_fname, expected_text, expected_data)
168 data = tools.ReadFile(elf_fname)
172 expected = expected_text + expected_data
173 self.assertEqual(elf.ElfInfo(expected, load, entry, len(expected)),
174 elf.DecodeElf(data, 0))
175 self.assertEqual(elf.ElfInfo(b'\0\0' + expected[2:],
176 load, entry, len(expected)),
177 elf.DecodeElf(data, load + 2))
178 #shutil.rmtree(outdir)
181 if __name__ == '__main__':