[U-Boot] [PATCH] sandbox: Improve debugging in initcall_run_list()

Simon Glass sjg at chromium.org
Sun Nov 18 20:19:48 UTC 2018


At present if one of the initcalls fails on sandbox the address printing
is not help, e.g.:

  initcall sequence 0000557678967c80 failed at call 00005576709dfe1f (err=-96)

This is because U-Boot gets relocated high into memory and the relocation
offset (gd->reloc_off) does not work correctly for sandbox.

Add support for finding the base address of the text region (at least on
Linux) and use that to set the relocation offset. This makes the output
better:

  initcall sequence 0000560775957c80 failed at call 0000000000048134 (err=-96)

Then you use can use grep to see which init call failed, e.g.:

   $ grep 0000000000048134 u-boot.map
   stdio_add_devices

Of course another option is to run it with a debugger such as gdb:

   $ gdb u-boot
   ...
   (gdb) br initcall.c:32
   Breakpoint 1 at 0x5555555e388f: file lib/initcall.c, line 32.
   (gdb) r
   Starting program: /tmp/b/sandbox/u-boot
   [Thread debugging using libthread_db enabled]
   Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

   U-Boot 2018.09-00264-ge0c2ba9814-dirty (Sep 22 2018 - 12:21:46 -0600)

   DRAM:  128 MiB
   MMC:

   Breakpoint 1, initcall_run_list (init_sequence=init_sequence at entry=0x5555558b5c80 <init_sequence_r>)
       at lib/initcall.c:32
   32				printf("initcall sequence %p failed at call %p (err=%d)\n",
   (gdb) print *init_fnc_ptr
   $1 = (const init_fnc_t) 0x55555559c114 <stdio_add_devices>
   (gdb)

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

 arch/sandbox/cpu/os.c                  | 37 ++++++++++++++++++++++++++
 arch/sandbox/cpu/start.c               |  1 +
 arch/sandbox/include/asm/global_data.h |  1 +
 common/board_f.c                       |  2 ++
 include/os.h                           | 11 ++++++++
 5 files changed, 52 insertions(+)

diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 325ded51d8a..8f6c5dbb2cd 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -706,3 +706,40 @@ int os_mprotect_allow(void *start, size_t len)
 
 	return mprotect(start, len, PROT_READ | PROT_WRITE);
 }
+
+void *os_find_text_base(struct sandbox_state *state)
+{
+	char line[500];
+	void *base = NULL;
+	int len;
+	int fd;
+
+	/*
+	 * This code assumes that the first line of /proc/self/maps holds
+	 * information about the text, for example:
+	 *
+	 * 5622d9907000-5622d9a55000 r-xp 00000000 08:01 15067168   u-boot
+	 *
+	 * The first hex value is assumed to be the address.
+	 *
+	 * This is tested in Linux 4.15.
+	 */
+	fd = open("/proc/self/maps", O_RDONLY);
+	if (fd == -1)
+		return NULL;
+	len = read(fd, line, sizeof(line));
+	if (len > 0) {
+		char *end = memchr(line, '-', len);
+
+		if (end) {
+			unsigned long long addr;
+
+			*end = '\0';
+			if (sscanf(line, "%llx", &addr) == 1)
+				base = (void *)addr;
+		}
+	}
+	close(fd);
+
+	return base;
+}
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 2ee3b485657..17c95f89352 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -323,6 +323,7 @@ int main(int argc, char *argv[])
 	gd->default_log_level = state->default_log_level;
 #endif
 	setup_ram_buf(state);
+	gd->arch.text_base = os_find_text_base(state);
 
 	/* Do pre- and post-relocation init */
 	board_init_f(0);
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index f6a6a343d25..f4ce72d5660 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -12,6 +12,7 @@
 /* Architecture-specific global data */
 struct arch_global_data {
 	uint8_t		*ram_buf;	/* emulated RAM buffer */
+	void		*text_base;	/* pointer to base of text region */
 };
 
 #include <asm-generic/global_data.h>
diff --git a/common/board_f.c b/common/board_f.c
index f1a1432d869..4600a73db1b 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -682,6 +682,8 @@ static int setup_reloc(void)
 	 * just after the default vector table location, so at 0x400
 	 */
 	gd->reloc_off = gd->relocaddr - (CONFIG_SYS_TEXT_BASE + 0x400);
+#elif defined(CONFIG_SANDBOX)
+	gd->reloc_off = gd->arch.text_base;
 #else
 	gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE;
 #endif
diff --git a/include/os.h b/include/os.h
index 28eb6252849..9224c743d1a 100644
--- a/include/os.h
+++ b/include/os.h
@@ -350,4 +350,15 @@ int os_mprotect_allow(void *start, size_t len);
  */
 int os_write_file(const char *name, const void *buf, int size);
 
+/**
+ * os_find_text_base() - Find the text section in this running process
+ *
+ * This tries to find the address of the text section in this running process.
+ * It can be useful to map the address of functions to the address listed in
+ * the u-boot.map file.
+ *
+ * @return address if found, else NULL
+ */
+void *os_find_text_base(struct sandbox_state *state);
+
 #endif
-- 
2.19.1.1215.g8438c0b245-goog



More information about the U-Boot mailing list