mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-20 20:04:46 +00:00
binman: Support positioning an entry by and ELF symbol
In some cases it is useful to position an entry over the top of a symbol in an ELF file. For example, if the symbol holds a version string then it allows the string to be accessed from the fdtmap. Add support for this. Suggested-by: Pali Rohár <pali@kernel.org> Suggested-by: Keith Short <keithshort@chromium.org> Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
8f5afe21ae
commit
571bc4e67d
5 changed files with 106 additions and 1 deletions
|
@ -823,6 +823,13 @@ elf-base-sym:
|
||||||
needed. Add this symbol to the properties for the blob so that symbols can
|
needed. Add this symbol to the properties for the blob so that symbols can
|
||||||
be read correctly. See binman_syms_ for more information.
|
be read correctly. See binman_syms_ for more information.
|
||||||
|
|
||||||
|
offset-from-elf:
|
||||||
|
Sets the offset of an entry based on a symbol value in an another entry.
|
||||||
|
The format is <&phandle>, "sym_name", <offset> where phandle is the entry
|
||||||
|
containing the blob (with associated ELF file providing symbols), <sym_name>
|
||||||
|
is the symbol to lookup (relative to elf-base-sym) and <offset> is an offset
|
||||||
|
to add to that value.
|
||||||
|
|
||||||
Examples of the above options can be found in the tests. See the
|
Examples of the above options can be found in the tests. See the
|
||||||
tools/binman/test directory.
|
tools/binman/test directory.
|
||||||
|
|
||||||
|
|
|
@ -210,6 +210,29 @@ def GetPackString(sym, msg):
|
||||||
raise ValueError('%s has size %d: only 4 and 8 are supported' %
|
raise ValueError('%s has size %d: only 4 and 8 are supported' %
|
||||||
(msg, sym.size))
|
(msg, sym.size))
|
||||||
|
|
||||||
|
def GetSymbolOffset(elf_fname, sym_name, base_sym=None):
|
||||||
|
"""Read the offset of a symbol compared to base symbol
|
||||||
|
|
||||||
|
This is useful for obtaining the value of a single symbol relative to the
|
||||||
|
base of a binary blob.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
elf_fname: Filename of the ELF file to read
|
||||||
|
sym_name (str): Name of symbol to read
|
||||||
|
base_sym (str): Base symbol to sue to calculate the offset (or None to
|
||||||
|
use '__image_copy_start'
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Offset of the symbol relative to the base symbol
|
||||||
|
"""
|
||||||
|
if not base_sym:
|
||||||
|
base_sym = '__image_copy_start'
|
||||||
|
fname = tools.get_input_filename(elf_fname)
|
||||||
|
syms = GetSymbols(fname, [base_sym, sym_name])
|
||||||
|
base = syms[base_sym].address
|
||||||
|
val = syms[sym_name].address
|
||||||
|
return val - base
|
||||||
|
|
||||||
def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False,
|
def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False,
|
||||||
base_sym=None):
|
base_sym=None):
|
||||||
"""Replace all symbols in an entry with their correct values
|
"""Replace all symbols in an entry with their correct values
|
||||||
|
|
|
@ -145,6 +145,7 @@ class Entry(object):
|
||||||
self.optional = False
|
self.optional = False
|
||||||
self.overlap = False
|
self.overlap = False
|
||||||
self.elf_base_sym = None
|
self.elf_base_sym = None
|
||||||
|
self.offset_from_elf = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def FindEntryClass(etype, expanded):
|
def FindEntryClass(etype, expanded):
|
||||||
|
@ -303,6 +304,8 @@ class Entry(object):
|
||||||
|
|
||||||
# This is only supported by blobs and sections at present
|
# This is only supported by blobs and sections at present
|
||||||
self.compress = fdt_util.GetString(self._node, 'compress', 'none')
|
self.compress = fdt_util.GetString(self._node, 'compress', 'none')
|
||||||
|
self.offset_from_elf = fdt_util.GetPhandleNameOffset(self._node,
|
||||||
|
'offset-from-elf')
|
||||||
|
|
||||||
def GetDefaultFilename(self):
|
def GetDefaultFilename(self):
|
||||||
return None
|
return None
|
||||||
|
@ -499,7 +502,10 @@ class Entry(object):
|
||||||
if self.offset_unset:
|
if self.offset_unset:
|
||||||
self.Raise('No offset set with offset-unset: should another '
|
self.Raise('No offset set with offset-unset: should another '
|
||||||
'entry provide this correct offset?')
|
'entry provide this correct offset?')
|
||||||
self.offset = tools.align(offset, self.align)
|
elif self.offset_from_elf:
|
||||||
|
self.offset = self.lookup_offset()
|
||||||
|
else:
|
||||||
|
self.offset = tools.align(offset, self.align)
|
||||||
needed = self.pad_before + self.contents_size + self.pad_after
|
needed = self.pad_before + self.contents_size + self.pad_after
|
||||||
needed = tools.align(needed, self.align_size)
|
needed = tools.align(needed, self.align_size)
|
||||||
size = self.size
|
size = self.size
|
||||||
|
@ -1328,3 +1334,14 @@ features to produce new behaviours.
|
||||||
int: entry address of ELF file
|
int: entry address of ELF file
|
||||||
"""
|
"""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def lookup_offset(self):
|
||||||
|
node, sym_name, offset = self.offset_from_elf
|
||||||
|
entry = self.section.FindEntryByNode(node)
|
||||||
|
if not entry:
|
||||||
|
self.Raise("Cannot find entry for node '%s'" % node.name)
|
||||||
|
if not entry.elf_fname:
|
||||||
|
entry.Raise("Need elf-fname property '%s'" % node.name)
|
||||||
|
val = elf.GetSymbolOffset(entry.elf_fname, sym_name,
|
||||||
|
entry.elf_base_sym)
|
||||||
|
return val + offset
|
||||||
|
|
|
@ -6281,6 +6281,34 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
|
||||||
expected = sym_values
|
expected = sym_values
|
||||||
self.assertEqual(expected, data[:len(expected)])
|
self.assertEqual(expected, data[:len(expected)])
|
||||||
|
|
||||||
|
def testOffsetFromElf(self):
|
||||||
|
"""Test a blob with symbols read from an ELF file"""
|
||||||
|
elf_fname = self.ElfTestFile('blob_syms')
|
||||||
|
TestFunctional._MakeInputFile('blob_syms', tools.read_file(elf_fname))
|
||||||
|
TestFunctional._MakeInputFile('blob_syms.bin',
|
||||||
|
tools.read_file(self.ElfTestFile('blob_syms.bin')))
|
||||||
|
|
||||||
|
data = self._DoReadFile('274_offset_from_elf.dts')
|
||||||
|
|
||||||
|
syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
|
||||||
|
base = elf.GetSymbolAddress(elf_fname, '__my_start_sym')
|
||||||
|
|
||||||
|
image = control.images['image']
|
||||||
|
entries = image.GetEntries()
|
||||||
|
|
||||||
|
self.assertIn('inset', entries)
|
||||||
|
inset = entries['inset']
|
||||||
|
|
||||||
|
self.assertEqual(base + 4, inset.offset);
|
||||||
|
self.assertEqual(base + 4, inset.image_pos);
|
||||||
|
self.assertEqual(4, inset.size);
|
||||||
|
|
||||||
|
self.assertIn('inset2', entries)
|
||||||
|
inset = entries['inset2']
|
||||||
|
self.assertEqual(base + 8, inset.offset);
|
||||||
|
self.assertEqual(base + 8, inset.image_pos);
|
||||||
|
self.assertEqual(4, inset.size);
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
30
tools/binman/test/274_offset_from_elf.dts
Normal file
30
tools/binman/test/274_offset_from_elf.dts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
binman {
|
||||||
|
blob: blob {
|
||||||
|
filename = "blob_syms.bin";
|
||||||
|
elf-filename = "blob_syms";
|
||||||
|
elf-base-sym = "__my_start_sym";
|
||||||
|
};
|
||||||
|
|
||||||
|
inset {
|
||||||
|
type = "null";
|
||||||
|
offset-from-elf = <&blob>, "val3", <0>;
|
||||||
|
size = <4>;
|
||||||
|
overlap;
|
||||||
|
};
|
||||||
|
|
||||||
|
inset2 {
|
||||||
|
type = "null";
|
||||||
|
offset-from-elf = <&blob>, "val3", <4>;
|
||||||
|
size = <4>;
|
||||||
|
overlap;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue