All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: U-Boot Mailing List <u-boot@lists.denx.de>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>,
	Bin Meng <bmeng.cn@gmail.com>,
	Christian Melki <christian.melki@t2data.com>,
	Tom Rini <trini@konsulko.com>,
	Ilias Apalodimas <ilias.apalodimas@linaro.org>,
	Simon Glass <sjg@chromium.org>
Subject: [PATCH v2 20/39] binman: Support reading the offset of an ELF-file symbol
Date: Fri, 24 Sep 2021 18:30:36 -0600	[thread overview]
Message-ID: <20210925003055.759305-8-sjg@chromium.org> (raw)
In-Reply-To: <20210925003055.759305-1-sjg@chromium.org>

Binman needs to be able to update the contents of an ELF file after it has
been build. To support this, add a function to locate the position of a
symbol's contents within the file.

Fix the comments on bss_data.c and Symbol while we are here.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 tools/binman/elf.py              | 53 ++++++++++++++++++++++++++++++--
 tools/binman/elf_test.py         | 37 ++++++++++++++++++++++
 tools/binman/test/Makefile       |  5 ++-
 tools/binman/test/bss_data.c     |  2 +-
 tools/binman/test/embed_data.c   | 16 ++++++++++
 tools/binman/test/embed_data.lds | 23 ++++++++++++++
 6 files changed, 131 insertions(+), 5 deletions(-)
 create mode 100644 tools/binman/test/embed_data.c
 create mode 100644 tools/binman/test/embed_data.lds

diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 03b49d7163c..4aca4f847ce 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -24,7 +24,14 @@ try:
 except:  # pragma: no cover
     ELF_TOOLS = False
 
-Symbol = namedtuple('Symbol', ['section', 'address', 'size', 'weak'])
+# Information about an EFL symbol:
+# section (str): Name of the section containing this symbol
+# address (int): Address of the symbol (its value)
+# size (int): Size of the symbol in bytes
+# weak (bool): True if the symbol is weak
+# offset (int or None): Offset of the symbol's data in the ELF file, or None if
+#   not known
+Symbol = namedtuple('Symbol', ['section', 'address', 'size', 'weak', 'offset'])
 
 # Information about an ELF file:
 #    data: Extracted program contents of ELF file (this would be loaded by an
@@ -71,8 +78,48 @@ def GetSymbols(fname, patterns):
         section, size =  parts[:2]
         if len(parts) > 2:
             name = parts[2] if parts[2] != '.hidden' else parts[3]
-            syms[name] = Symbol(section, int(value, 16), int(size,16),
-                                flags[1] == 'w')
+            syms[name] = Symbol(section, int(value, 16), int(size, 16),
+                                flags[1] == 'w', None)
+
+    # Sort dict by address
+    return OrderedDict(sorted(syms.items(), key=lambda x: x[1].address))
+
+def GetSymbolFileOffset(fname, patterns):
+    """Get the symbols from an ELF file
+
+    Args:
+        fname: Filename of the ELF file to read
+        patterns: List of regex patterns to search for, each a string
+
+    Returns:
+        None, if the file does not exist, or Dict:
+          key: Name of symbol
+          value: Hex value of symbol
+    """
+    def _GetFileOffset(elf, addr):
+        for seg in elf.iter_segments():
+            seg_end = seg['p_vaddr'] + seg['p_filesz']
+            if seg.header['p_type'] == 'PT_LOAD':
+                if addr >= seg['p_vaddr'] and addr < seg_end:
+                    return addr - seg['p_vaddr'] + seg['p_offset']
+
+    if not ELF_TOOLS:
+        raise ValueError('Python elftools package is not available')
+
+    syms = {}
+    with open(fname, 'rb') as fd:
+        elf = ELFFile(fd)
+
+        re_syms = re.compile('|'.join(patterns))
+        for section in elf.iter_sections():
+            if isinstance(section, SymbolTableSection):
+                for symbol in section.iter_symbols():
+                    if not re_syms or re_syms.search(symbol.name):
+                        addr = symbol.entry['st_value']
+                        syms[symbol.name] = Symbol(
+                            section.name, addr, symbol.entry['st_size'],
+                            symbol.entry['st_info']['bind'] == 'STB_WEAK',
+                            _GetFileOffset(elf, addr))
 
     # Sort dict by address
     return OrderedDict(sorted(syms.items(), key=lambda x: x[1].address))
diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py
index bcccd78c0a1..ac69a95b654 100644
--- a/tools/binman/elf_test.py
+++ b/tools/binman/elf_test.py
@@ -6,6 +6,7 @@
 
 import os
 import shutil
+import struct
 import sys
 import tempfile
 import unittest
@@ -221,6 +222,42 @@ class TestElf(unittest.TestCase):
                          elf.DecodeElf(data, load + 2))
         shutil.rmtree(outdir)
 
+    def testEmbedData(self):
+        """Test for the GetSymbolFileOffset() function"""
+        if not elf.ELF_TOOLS:
+            self.skipTest('Python elftools not available')
+
+        fname = self.ElfTestFile('embed_data')
+        offset = elf.GetSymbolFileOffset(fname, ['embed_start', 'embed_end'])
+        start = offset['embed_start'].offset
+        end = offset['embed_end'].offset
+        data = tools.ReadFile(fname)
+        embed_data = data[start:end]
+        expect = struct.pack('<III', 0x1234, 0x5678, 0)
+        self.assertEqual(expect, embed_data)
+
+    def testEmbedFail(self):
+        """Test calling GetSymbolFileOffset() without elftools"""
+        try:
+            old_val = elf.ELF_TOOLS
+            elf.ELF_TOOLS = False
+            fname = self.ElfTestFile('embed_data')
+            with self.assertRaises(ValueError) as e:
+                elf.GetSymbolFileOffset(fname, ['embed_start', 'embed_end'])
+            self.assertIn('Python elftools package is not available',
+                      str(e.exception))
+        finally:
+            elf.ELF_TOOLS = old_val
+
+    def testEmbedDataNoSym(self):
+        """Test for GetSymbolFileOffset() getting no symbols"""
+        if not elf.ELF_TOOLS:
+            self.skipTest('Python elftools not available')
+
+        fname = self.ElfTestFile('embed_data')
+        offset = elf.GetSymbolFileOffset(fname, ['missing_sym'])
+        self.assertEqual({}, offset)
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tools/binman/test/Makefile b/tools/binman/test/Makefile
index 0b19b7d9935..6e6cc6de491 100644
--- a/tools/binman/test/Makefile
+++ b/tools/binman/test/Makefile
@@ -31,7 +31,7 @@ LDS_BINMAN_X86 := -T $(SRC)u_boot_binman_syms_x86.lds
 
 TARGETS = u_boot_ucode_ptr u_boot_no_ucode_ptr bss_data \
 	u_boot_binman_syms u_boot_binman_syms.bin u_boot_binman_syms_bad \
-	u_boot_binman_syms_size u_boot_binman_syms_x86
+	u_boot_binman_syms_size u_boot_binman_syms_x86 embed_data
 
 all: $(TARGETS)
 
@@ -44,6 +44,9 @@ u_boot_ucode_ptr: u_boot_ucode_ptr.c
 bss_data: CFLAGS += $(SRC)bss_data.lds
 bss_data: bss_data.c
 
+embed_data: CFLAGS += $(SRC)embed_data.lds
+embed_data: embed_data.c
+
 u_boot_binman_syms.bin: u_boot_binman_syms
 	$(OBJCOPY) -O binary $< -R .note.gnu.build-id $@
 
diff --git a/tools/binman/test/bss_data.c b/tools/binman/test/bss_data.c
index 79537c31b65..4f9b64cef9e 100644
--- a/tools/binman/test/bss_data.c
+++ b/tools/binman/test/bss_data.c
@@ -2,7 +2,7 @@
 /*
  * Copyright (c) 2016 Google, Inc
  *
- * Simple program to create a _dt_ucode_base_size symbol which can be read
+ * Simple program to create a bss_data region so the symbol can be read
  * by binutils. This is used by binman tests.
  */
 
diff --git a/tools/binman/test/embed_data.c b/tools/binman/test/embed_data.c
new file mode 100644
index 00000000000..47d8c38248c
--- /dev/null
+++ b/tools/binman/test/embed_data.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Simple program including some embedded data that can be accessed by binman.
+ * This is used by binman tests.
+ */
+
+int first[10] = {1};
+int embed[3] __attribute__((section(".embed"))) = {0x1234, 0x5678};
+int second[10] = {1};
+
+int main(void)
+{
+	return 0;
+}
diff --git a/tools/binman/test/embed_data.lds b/tools/binman/test/embed_data.lds
new file mode 100644
index 00000000000..908bf66c294
--- /dev/null
+++ b/tools/binman/test/embed_data.lds
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 Google LLC
+ */
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+	_start = .;
+	__data_start = .;
+	.data :
+	{
+		. = ALIGN(32);
+		embed_start = .;
+		*(.embed*)
+		embed_end = .;
+		. = ALIGN(32);
+		*(.data*)
+	}
+}
-- 
2.33.0.685.g46640cef36-goog


  parent reply	other threads:[~2021-09-25  0:36 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-25  0:30 [PATCH v2 00/39] efi: Improvements to U-Boot running on top of UEFI Simon Glass
2021-09-25  0:30 ` [PATCH v2 01/39] RFC: efi: Drop code that doesn't work with driver model Simon Glass
2021-10-20 23:34   ` Heinrich Schuchardt
2022-10-14 11:51     ` Jan Kiszka
2022-10-14 13:13       ` Tom Rini
2022-10-14 15:33         ` Simon Glass
2022-10-14 15:34           ` Jan Kiszka
2022-10-14 15:36             ` Simon Glass
2022-10-14 15:39               ` Tom Rini
2022-10-14 15:47                 ` Jan Kiszka
2022-10-14 15:58                   ` Tom Rini
2022-10-14 15:10       ` Heinrich Schuchardt
2022-10-14 15:20         ` Tom Rini
2022-10-14 15:27           ` Jan Kiszka
2022-10-14 15:34             ` Tom Rini
2022-10-14 15:35               ` Jan Kiszka
2022-10-14 15:38                 ` Tom Rini
2022-10-14 15:25         ` Jan Kiszka
2021-09-25  0:30 ` [PATCH v2 02/39] efi: Add a separate maintainer entry for the app Simon Glass
2021-10-18 16:36   ` Heinrich Schuchardt
2021-09-25  0:30 ` [PATCH v2 03/39] x86: Keep symbol information in u-boot ELF file Simon Glass
2021-09-25  0:30 ` [PATCH v2 04/39] x86: Create a new header for EFI Simon Glass
2021-10-18 17:00   ` Heinrich Schuchardt
2021-09-25  0:30 ` [PATCH v2 05/39] x86: Show some EFI info with the bdinfo command Simon Glass
2021-10-18 17:10   ` Heinrich Schuchardt
2021-10-26  3:29     ` Simon Glass
2021-09-25  0:30 ` [PATCH v2 06/39] x86: Tidy up global_data pointer for 64-bit Simon Glass
2021-10-18 17:15   ` Heinrich Schuchardt
2021-10-26  3:29     ` Simon Glass
2021-09-25  0:30 ` [PATCH v2 07/39] efi: Add a script for building and testing U-Boot on UEFI Simon Glass
2021-10-18 17:30   ` Heinrich Schuchardt
2021-10-18 18:12     ` Simon Glass
2021-10-25 19:35   ` Heinrich Schuchardt
2021-10-26  3:29     ` Simon Glass
2021-09-25  0:30 ` [PATCH v2 08/39] efi: Enable DM_ETH for the app Simon Glass
2021-09-25  0:30 ` [PATCH v2 09/39] efi: Drop the OF_EMBED warning for EFI Simon Glass
2021-10-23 11:37   ` Heinrich Schuchardt
2021-10-26  3:29     ` Simon Glass
2021-09-25  0:30 ` [PATCH v2 10/39] x86: Create a 32/64-bit selection for the app Simon Glass
2021-10-23 11:41   ` Heinrich Schuchardt
2021-09-25  0:30 ` [PATCH v2 11/39] efi: Create a 64-bit app Simon Glass
2021-09-25  0:30 ` [PATCH v2 12/39] x86: Don't duplicate global_ptr in 64-bit EFI app Simon Glass
2021-09-25  0:30 ` [PATCH v2 13/39] efi: Add a way to obtain boot services in the app Simon Glass
2021-09-25  0:30 ` [PATCH v2 14/39] efi: Add video support to " Simon Glass
2021-09-25  0:30 ` [PATCH v2 15/39] efi: Add EFI uclass for media Simon Glass
2021-10-23 12:26   ` Heinrich Schuchardt
2021-10-26  3:29     ` Simon Glass
2021-09-25  0:30 ` [PATCH v2 16/39] efi: Add a media/block driver for EFI block devices Simon Glass
2021-09-25  0:30 ` [PATCH v2 17/39] efi: Locate all block devices in the app Simon Glass
2021-09-25  0:30 ` [PATCH v2 18/39] patman: Use a ValueError exception if tools.Run() fails Simon Glass
2021-09-25  0:30 ` [PATCH v2 19/39] binman: Report an error if test files fail to compile Simon Glass
2021-09-25  0:30 ` Simon Glass [this message]
2021-09-25  0:30 ` [PATCH v2 21/39] binman: Allow timeout to occur in the image or its section Simon Glass
2021-09-25  0:30 ` [PATCH v2 22/39] binman: Tidy up comments on _DoTestFile() Simon Glass
2021-09-25  0:30 ` [PATCH v2 23/39] binman: Support updating the dtb in an ELF file Simon Glass
2021-09-25  0:30 ` [PATCH v2 24/39] efi: serial: Support arrow keys Simon Glass
2021-10-18 16:55   ` Heinrich Schuchardt
2021-10-26  3:29     ` Simon Glass
2021-09-25  0:30 ` [PATCH v2 25/39] bloblist: Support allocating the bloblist Simon Glass
2021-09-25  0:30 ` [PATCH v2 26/39] x86: Allow booting a kernel from the EFI app Simon Glass
2021-09-25  0:30 ` [PATCH v2 27/39] x86: Don't process the kernel command line unless enabled Simon Glass
2021-09-25  0:30 ` [PATCH v2 28/39] x86: efi: Add room for the binman definition in the dtb Simon Glass
2021-09-25  0:30 ` [PATCH v2 29/39] efi: Add comments to struct efi_priv Simon Glass
2021-10-23 11:28   ` Heinrich Schuchardt
2021-09-25  0:30 ` [PATCH v2 30/39] efi: Fix ll_boot_init() operation with the app Simon Glass
2021-09-25  0:30 ` [PATCH v2 32/39] efi: Share struct efi_priv between the app and stub code Simon Glass
2021-09-25  0:30 ` [PATCH v2 33/39] efi: Move exit_boot_services into a function Simon Glass
2021-09-25  0:30 ` [PATCH v2 34/39] efi: Check for failure when initing the app Simon Glass
2021-09-25  0:30 ` [PATCH v2 35/39] efi: Mention that efi_info_get() is only used in the stub Simon Glass
2021-09-25  0:30 ` [PATCH v2 36/39] efi: Show when allocated pages are used Simon Glass
2021-09-25  0:30 ` [PATCH v2 37/39] efi: Allow easy selection of serial-only operation Simon Glass
2021-09-25  0:30 ` [PATCH v2 38/39] efi: Update efi_get_next_mem_desc() to avoid needing a map Simon Glass
2021-09-25  0:30 ` [PATCH v2 39/39] efi: Support the efi command in the app Simon Glass
2021-10-18 15:25 ` [PATCH v2 00/39] efi: Improvements to U-Boot running on top of UEFI Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210925003055.759305-8-sjg@chromium.org \
    --to=sjg@chromium.org \
    --cc=bmeng.cn@gmail.com \
    --cc=christian.melki@t2data.com \
    --cc=ilias.apalodimas@linaro.org \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    --cc=xypron.glpk@gmx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.