Patchwork linux-user/FLAT: allow targets to override FLAT reloc processing

login
register
mail settings
Submitter Mike Frysinger
Date Jan. 24, 2011, 9:48 a.m.
Message ID <1295862517-6668-1-git-send-email-vapier@gentoo.org>
Download mbox | patch
Permalink /patch/80144/
State New
Headers show

Comments

Mike Frysinger - Jan. 24, 2011, 9:48 a.m.
This brings flatload.c more in line with the current Linux FLAT loader
which allows targets to handle FLAT relocations in their own way.  For
the common behavior, the new functions get stubbed out.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
 Makefile.target          |    2 +-
 linux-user/flatload.c    |   24 +++++++++---------------
 linux-user/target_flat.h |    9 +++++++++
 3 files changed, 19 insertions(+), 16 deletions(-)
 create mode 100644 linux-user/target_flat.h
Riku Voipio - Jan. 26, 2011, 9:21 p.m.
On 01/24/2011 11:48 AM, Mike Frysinger wrote:
> This brings flatload.c more in line with the current Linux FLAT loader
> which allows targets to handle FLAT relocations in their own way.  For
> the common behavior, the new functions get stubbed out.

Do you have some instructions howto build flat binaries for testing? I 
have to admit my knowledge of flat binaries is quite nonexisting.

Riku

> Signed-off-by: Mike Frysinger<vapier@gentoo.org>
> ---
>   Makefile.target          |    2 +-
>   linux-user/flatload.c    |   24 +++++++++---------------
>   linux-user/target_flat.h |    9 +++++++++
>   3 files changed, 19 insertions(+), 16 deletions(-)
>   create mode 100644 linux-user/target_flat.h
>
> diff --git a/Makefile.target b/Makefile.target
> index cd2abde..282428b 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -107,7 +107,7 @@ ifdef CONFIG_LINUX_USER
>
>   $(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR))
>
> -QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
> +QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
>   obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
>         elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
>         qemu-malloc.o $(oslib-obj-y)
> diff --git a/linux-user/flatload.c b/linux-user/flatload.c
> index d8b4476..c133732 100644
> --- a/linux-user/flatload.c
> +++ b/linux-user/flatload.c
> @@ -41,6 +41,8 @@
>
>   #include "qemu.h"
>   #include "flat.h"
> +#define ntohl(x) be32_to_cpu(x)
> +#include<target_flat.h>
>
>   //#define DEBUG
>
> @@ -50,14 +52,6 @@
>   #define	DBG_FLT(...)
>   #endif
>
> -#define flat_reloc_valid(reloc, size)             ((reloc)<= (size))
> -#define flat_old_ram_flag(flag)                   (flag)
> -#ifdef TARGET_WORDS_BIGENDIAN
> -#define flat_get_relocate_addr(relval)            (relval)
> -#else
> -#define flat_get_relocate_addr(relval)            bswap32(relval)
> -#endif
> -
>   #define RELOC_FAILED 0xff00ff01		/* Relocation incorrect somewhere */
>   #define UNLOADED_LIB 0x7ff000ff		/* Placeholder for unused library */
>
> @@ -78,8 +72,6 @@ static int load_flat_shared_library(int id, struct lib_info *p);
>
>   struct linux_binprm;
>
> -#define ntohl(x) be32_to_cpu(x)
> -
>   /****************************************************************************/
>   /*
>    * create_flat_tables() parses the env- and arg-strings in new user
> @@ -625,6 +617,7 @@ static int load_flat_file(struct linux_binprm * bprm,
>        * __start to address 4 so that is okay).
>        */
>       if (rev>  OLD_FLAT_VERSION) {
> +        abi_ulong persistent = 0;
>           for (i = 0; i<  relocs; i++) {
>               abi_ulong addr, relval;
>
> @@ -633,6 +626,9 @@ static int load_flat_file(struct linux_binprm * bprm,
>                  relocated first).  */
>               if (get_user_ual(relval, reloc + i * sizeof(abi_ulong)))
>                   return -EFAULT;
> +            relval = ntohl(relval);
> +            if (flat_set_persistent(relval,&persistent))
> +                continue;
>               addr = flat_get_relocate_addr(relval);
>               rp = calc_reloc(addr, libinfo, id, 1);
>               if (rp == RELOC_FAILED)
> @@ -641,22 +637,20 @@ static int load_flat_file(struct linux_binprm * bprm,
>               /* Get the pointer's value.  */
>               if (get_user_ual(addr, rp))
>                   return -EFAULT;
> +            addr = flat_get_addr_from_rp(rp, relval, flags,&persistent);
>               if (addr != 0) {
>                   /*
>                    * Do the relocation.  PIC relocs in the data section are
>                    * already in target order
>                    */
> -
> -#ifndef TARGET_WORDS_BIGENDIAN
>                   if ((flags&  FLAT_FLAG_GOTPIC) == 0)
> -                    addr = bswap32(addr);
> -#endif
> +                    addr = ntohl(addr);
>                   addr = calc_reloc(addr, libinfo, id, 0);
>                   if (addr == RELOC_FAILED)
>                       return -ENOEXEC;
>
>                   /* Write back the relocated pointer.  */
> -                if (put_user_ual(addr, rp))
> +                if (flat_put_addr_at_rp(rp, addr, relval))
>                       return -EFAULT;
>               }
>           }
> diff --git a/linux-user/target_flat.h b/linux-user/target_flat.h
> new file mode 100644
> index 0000000..332b6e3
> --- /dev/null
> +++ b/linux-user/target_flat.h
> @@ -0,0 +1,9 @@
> +/* If your arch needs to do custom stuff, create your own target_flat.h
> + * header file in linux-user/<your arch>/
> + */
> +#define flat_reloc_valid(reloc, size)                        ((reloc)<= (size))
> +#define flat_old_ram_flag(flag)                              (flag)
> +#define flat_get_relocate_addr(relval)                       (relval)
> +#define flat_get_addr_from_rp(rp, relval, flags, persistent) (rp)
> +#define flat_set_persistent(relval, persistent)              (*persistent)
> +#define flat_put_addr_at_rp(rp, addr, relval)                put_user_ual(addr, rp)
Mike Frysinger - Jan. 27, 2011, 12:19 a.m.
On Wed, Jan 26, 2011 at 16:21, riku voipio wrote:
> On 01/24/2011 11:48 AM, Mike Frysinger wrote:
>> This brings flatload.c more in line with the current Linux FLAT loader
>> which allows targets to handle FLAT relocations in their own way.  For
>> the common behavior, the new functions get stubbed out.
>
> Do you have some instructions howto build flat binaries for testing? I have
> to admit my knowledge of flat binaries is quite nonexisting.

you would need to get a toolchain that specifically supports it.  a
simple binutils/gcc cross-compiler wont work because you need the
external "elf2flt" package integrated, and doing so is non-trivial.

personally, ive never used ARM/nommu, but i believe you want this toolchain:
http://www.codesourcery.com/sgpp/lite/arm/portal/release1588
and then simply compiling a simple app like:
  main(){puts("hello");}
should produce a FLAT file you can run.

this is how you do it for a Blackfin FLAT, and i imagine the ARM
method is the same:
$ echo 'main(){puts("hello");}' > test.c
$ bfin-uclinux-gcc test.c
$ file a.out
a.out: BFLT executable - version 4 ram
$ qemu-bfin ./a.out
hello
-mike

Patch

diff --git a/Makefile.target b/Makefile.target
index cd2abde..282428b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -107,7 +107,7 @@  ifdef CONFIG_LINUX_USER
 
 $(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR))
 
-QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
+QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
 obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
       elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
       qemu-malloc.o $(oslib-obj-y)
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index d8b4476..c133732 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -41,6 +41,8 @@ 
 
 #include "qemu.h"
 #include "flat.h"
+#define ntohl(x) be32_to_cpu(x)
+#include <target_flat.h>
 
 //#define DEBUG
 
@@ -50,14 +52,6 @@ 
 #define	DBG_FLT(...)
 #endif
 
-#define flat_reloc_valid(reloc, size)             ((reloc) <= (size))
-#define flat_old_ram_flag(flag)                   (flag)
-#ifdef TARGET_WORDS_BIGENDIAN
-#define flat_get_relocate_addr(relval)            (relval)
-#else
-#define flat_get_relocate_addr(relval)            bswap32(relval)
-#endif
-
 #define RELOC_FAILED 0xff00ff01		/* Relocation incorrect somewhere */
 #define UNLOADED_LIB 0x7ff000ff		/* Placeholder for unused library */
 
@@ -78,8 +72,6 @@  static int load_flat_shared_library(int id, struct lib_info *p);
 
 struct linux_binprm;
 
-#define ntohl(x) be32_to_cpu(x)
-
 /****************************************************************************/
 /*
  * create_flat_tables() parses the env- and arg-strings in new user
@@ -625,6 +617,7 @@  static int load_flat_file(struct linux_binprm * bprm,
      * __start to address 4 so that is okay).
      */
     if (rev > OLD_FLAT_VERSION) {
+        abi_ulong persistent = 0;
         for (i = 0; i < relocs; i++) {
             abi_ulong addr, relval;
 
@@ -633,6 +626,9 @@  static int load_flat_file(struct linux_binprm * bprm,
                relocated first).  */
             if (get_user_ual(relval, reloc + i * sizeof(abi_ulong)))
                 return -EFAULT;
+            relval = ntohl(relval);
+            if (flat_set_persistent(relval, &persistent))
+                continue;
             addr = flat_get_relocate_addr(relval);
             rp = calc_reloc(addr, libinfo, id, 1);
             if (rp == RELOC_FAILED)
@@ -641,22 +637,20 @@  static int load_flat_file(struct linux_binprm * bprm,
             /* Get the pointer's value.  */
             if (get_user_ual(addr, rp))
                 return -EFAULT;
+            addr = flat_get_addr_from_rp(rp, relval, flags, &persistent);
             if (addr != 0) {
                 /*
                  * Do the relocation.  PIC relocs in the data section are
                  * already in target order
                  */
-
-#ifndef TARGET_WORDS_BIGENDIAN
                 if ((flags & FLAT_FLAG_GOTPIC) == 0)
-                    addr = bswap32(addr);
-#endif
+                    addr = ntohl(addr);
                 addr = calc_reloc(addr, libinfo, id, 0);
                 if (addr == RELOC_FAILED)
                     return -ENOEXEC;
 
                 /* Write back the relocated pointer.  */
-                if (put_user_ual(addr, rp))
+                if (flat_put_addr_at_rp(rp, addr, relval))
                     return -EFAULT;
             }
         }
diff --git a/linux-user/target_flat.h b/linux-user/target_flat.h
new file mode 100644
index 0000000..332b6e3
--- /dev/null
+++ b/linux-user/target_flat.h
@@ -0,0 +1,9 @@ 
+/* If your arch needs to do custom stuff, create your own target_flat.h
+ * header file in linux-user/<your arch>/
+ */
+#define flat_reloc_valid(reloc, size)                        ((reloc) <= (size))
+#define flat_old_ram_flag(flag)                              (flag)
+#define flat_get_relocate_addr(relval)                       (relval)
+#define flat_get_addr_from_rp(rp, relval, flags, persistent) (rp)
+#define flat_set_persistent(relval, persistent)              (*persistent)
+#define flat_put_addr_at_rp(rp, addr, relval)                put_user_ual(addr, rp)