All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] linux-user/FLAT: allow targets to override FLAT reloc processing
@ 2008-10-11 19:06 Mike Frysinger
  0 siblings, 0 replies; 4+ messages in thread
From: Mike Frysinger @ 2008-10-11 19:06 UTC (permalink / raw)
  To: qemu-devel

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>
---
Note: i'd like to say these changes didn't break existing FLAT targets, but
i'm unable to verify that since all the FLAT targets i tested are already
broken (give me "reloc outside program" errors) ... i was able to verify
that existing behavior seemed to be unchanged though (same # of relocs
were processed with the same result).

 Makefile.target          |    2 +-
 linux-user/flatload.c    |   21 +++++++++------------
 linux-user/target_flat.h |    9 +++++++++
 3 files changed, 19 insertions(+), 13 deletions(-)
 create mode 100644 linux-user/target_flat.h

diff --git a/Makefile.target b/Makefile.target
index 0f0b7a0..6b9a52f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -321,7 +321,7 @@ ifndef TARGET_ABI_DIR
   TARGET_ABI_DIR=$(TARGET_ARCH)
 endif
 VPATH+=:$(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
-CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
+CPPFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
 
 ifdef CONFIG_STATIC
 LDFLAGS+=-static
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 543afeb..e63feb4 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -42,6 +42,8 @@
 
 #include "qemu.h"
 #include "flat.h"
+#define ntohl(x) be32_to_cpu(x)
+#include <target_flat.h>
 
 #define DEBUG
 
@@ -51,14 +53,6 @@
 #define	DBG_FLT(a...)
 #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 */
 
@@ -79,8 +73,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
@@ -339,7 +331,7 @@ failed:
 void old_reloc(struct lib_info *libinfo, uint32_t rl)
 {
 #ifdef DEBUG
-	char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
+	const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
 #endif
 	uint32_t *ptr;
         uint32_t offset;
@@ -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,6 +637,7 @@ 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
@@ -656,7 +653,7 @@ static int load_flat_file(struct linux_binprm * bprm,
                     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)
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 4+ messages in thread
* [Qemu-devel] [RFC/PATCH] elfload: add FDPIC support
@ 2011-01-09  8:48 Mike Frysinger
  2011-01-23 19:51 ` [Qemu-devel] [PATCH] linux-user/FLAT: allow targets to override FLAT reloc processing Mike Frysinger
  0 siblings, 1 reply; 4+ messages in thread
From: Mike Frysinger @ 2011-01-09  8:48 UTC (permalink / raw)
  To: qemu-devel

This is a PoC at this point, but it seems to be working for me.  At
least, all the current crashes I'm seeing are due to my Blackfin port
being incomplete.  All of the FDPIC table parsing seems to be OK ...

If someone with a more functional target would like to try this, that'd
be cool.  Or if people want to give feedback on how to approach this
problem so I can adjust the details now.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
 elf.h                |   19 ++++++++++++++
 linux-user/elfload.c |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 linux-user/qemu.h    |    8 ++++++
 3 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/elf.h b/elf.h
index 7067c90..d2f24f4 100644
--- a/elf.h
+++ b/elf.h
@@ -1191,6 +1191,25 @@ typedef struct elf64_note {
   Elf64_Word n_type;	/* Content type */
 } Elf64_Nhdr;
 
+
+/* This data structure represents a PT_LOAD segment.  */
+struct elf32_fdpic_loadseg {
+  /* Core address to which the segment is mapped.  */
+  Elf32_Addr addr;
+  /* VMA recorded in the program header.  */
+  Elf32_Addr p_vaddr;
+  /* Size of this segment in memory.  */
+  Elf32_Word p_memsz;
+};
+struct elf32_fdpic_loadmap {
+  /* Protocol version number, must be zero.  */
+  Elf32_Half version;
+  /* Number of segments in this map.  */
+  Elf32_Half nsegs;
+  /* The actual memory map.  */
+  struct elf32_fdpic_loadseg segs[/*nsegs*/];
+};
+
 #ifdef ELF_CLASS
 #if ELF_CLASS == ELFCLASS32
 
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 33d776d..8100ffd 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1075,6 +1075,32 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
     }
 }
 
+#ifdef CONFIG_USE_FDPIC
+static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp)
+{
+    uint16_t n;
+    struct elf32_fdpic_loadseg *loadsegs = info->loadsegs;
+
+    /* elf32_fdpic_loadseg */
+    for (n = 0; n < info->nsegs; ++n) {
+        sp -= 12;
+        put_user_u32(loadsegs[n].addr, sp+0);
+        put_user_u32(loadsegs[n].p_vaddr, sp+4);
+        put_user_u32(loadsegs[n].p_memsz, sp+8);
+    }
+
+    /* elf32_fdpic_loadmap */
+    sp -= 4;
+    put_user_u16(0, sp+0); /* version */
+    put_user_u16(info->nsegs, sp+2); /* nsegs */
+
+    info->personality = PER_LINUX_FDPIC;
+    info->loadmap_addr = sp;
+
+    return sp;
+}
+#endif
+
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr *exec,
                                    struct image_info *info,
@@ -1087,6 +1113,21 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     const int n = sizeof(elf_addr_t);
 
     sp = p;
+
+#ifdef CONFIG_USE_FDPIC
+    /* Needs to be before we load the env/argc/... */
+    if (elf_is_fdpic(exec)) {
+        /* Need 4 byte alignment for these structs */
+        sp &= ~3;
+        sp = loader_build_fdpic_loadmap(info, sp);
+        info->other_info = interp_info;
+        if (interp_info) {
+            interp_info->other_info = info;
+            sp = loader_build_fdpic_loadmap(interp_info, sp);
+        }
+    }
+#endif
+
     u_platform = 0;
     k_platform = ELF_PLATFORM;
     if (k_platform) {
@@ -1197,6 +1238,11 @@ static void load_elf_image(const char *image_name, int image_fd,
     }
     bswap_phdr(phdr, ehdr->e_phnum);
 
+#ifdef CONFIG_USE_FDPIC
+    info->nsegs = 0;
+    info->pt_dynamic_addr = 0;
+#endif
+
     /* Find the maximum size of the image and allocate an appropriate
        amount of memory to handle that.  */
     loaddr = -1, hiaddr = 0;
@@ -1210,6 +1256,11 @@ static void load_elf_image(const char *image_name, int image_fd,
             if (a > hiaddr) {
                 hiaddr = a;
             }
+#ifdef CONFIG_USE_FDPIC
+            ++info->nsegs;
+        } else if (phdr[i].p_type == PT_DYNAMIC) {
+            info->pt_dynamic_addr = phdr[i].p_vaddr;
+#endif
         }
     }
 
@@ -1290,6 +1341,22 @@ static void load_elf_image(const char *image_name, int image_fd,
     }
     load_bias = load_addr - loaddr;
 
+#ifdef CONFIG_USE_FDPIC
+    {
+        struct elf32_fdpic_loadseg *loadsegs = info->loadsegs =
+            qemu_malloc(sizeof(*loadsegs) * info->nsegs);
+
+        for (i = 0; i < ehdr->e_phnum; ++i) {
+            if (phdr[i].p_type != PT_LOAD)
+                continue;
+            loadsegs->addr = phdr[i].p_vaddr + load_bias;
+            loadsegs->p_vaddr = phdr[i].p_vaddr;
+            loadsegs->p_memsz = phdr[i].p_memsz;
+			++loadsegs;
+        }
+    }
+#endif
+
     info->load_bias = load_bias;
     info->load_addr = load_addr;
     info->entry = ehdr->e_entry + load_bias;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 32de241..0924a1a 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -51,6 +51,14 @@ struct image_info {
         abi_ulong       arg_start;
         abi_ulong       arg_end;
 	int		personality;
+#ifdef CONFIG_USE_FDPIC
+#define FDPIC_MAX_LOAD_SEGS 4
+        abi_ulong       loadmap_addr;
+        uint16_t        nsegs;
+        void           *loadsegs;
+        abi_ulong       pt_dynamic_addr;
+        struct image_info *other_info;
+#endif
 };
 
 #ifdef TARGET_I386
-- 
1.7.4.rc1

^ permalink raw reply related	[flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH] linux-user/FLAT: allow targets to override FLAT reloc processing
@ 2011-01-24  9:48 Mike Frysinger
  0 siblings, 0 replies; 4+ messages in thread
From: Mike Frysinger @ 2011-01-24  9:48 UTC (permalink / raw)
  To: qemu-devel, Riku Voipio

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

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)
-- 
1.7.4.rc2

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-01-24  9:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-11 19:06 [Qemu-devel] [PATCH] linux-user/FLAT: allow targets to override FLAT reloc processing Mike Frysinger
2011-01-09  8:48 [Qemu-devel] [RFC/PATCH] elfload: add FDPIC support Mike Frysinger
2011-01-23 19:51 ` [Qemu-devel] [PATCH] linux-user/FLAT: allow targets to override FLAT reloc processing Mike Frysinger
2011-01-23 19:54   ` Mike Frysinger
2011-01-24  9:48 Mike Frysinger

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.