sandbox: Improve debugging in initcall_run_list()

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.h:41
   Breakpoint 1 at 0x4db9d: initcall.h:41. (2 locations)

Note that two locations are reported, since this function is used in both
board_init_f() and board_init_r().

   (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=0x5555559619e0 <init_sequence_f>)
    at /scratch/sglass/cosarm/src/third_party/u-boot/files/include/initcall.h:41
41				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@chromium.org>
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index a8d01e4..c204914 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -786,3 +786,40 @@
 
 	return mprotect(start, len, PROT_READ | PROT_WRITE);
 }
+
+void *os_find_text_base(void)
+{
+	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 2f5e6e9..e22d65f 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -328,6 +328,10 @@
 	gd_t data;
 	int ret;
 
+	memset(&data, '\0', sizeof(data));
+	gd = &data;
+	gd->arch.text_base = os_find_text_base();
+
 	ret = state_init();
 	if (ret)
 		goto err;
@@ -340,8 +344,6 @@
 	if (ret)
 		goto err;
 
-	memset(&data, '\0', sizeof(data));
-	gd = &data;
 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
 	gd->malloc_base = CONFIG_MALLOC_F_ADDR;
 #endif
@@ -350,6 +352,12 @@
 #endif
 	setup_ram_buf(state);
 
+	/*
+	 * Set up the relocation offset here, since sandbox symbols are always
+	 * relocated by the OS before sandbox is entered.
+	 */
+	gd->reloc_off = (ulong)gd->arch.text_base;
+
 	/* 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 f6a6a34..f4ce72d 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>