qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] Re: [RFC/PATCH] elfload: add FDPIC support


From: Stefano Bonifazi
Subject: [Qemu-devel] Re: [RFC/PATCH] elfload: add FDPIC support
Date: Mon, 24 Jan 2011 14:34:12 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101208 Thunderbird/3.1.7

On 01/09/2011 09:48 AM, Mike Frysinger wrote:
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<address@hidden>
---
  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

Hi!
Could you be so kind of explaining me, or addressing me to what this patch would do? Is FDPIC something different than simply PIC code (position independent code)? I am also trying to fight with the problem of changing the starting address of target code for qemu-user, and I was just moving into the option of using PIC target code .. but the original qemu-user load_elf_binary does not work on them.. and I was just about to try to edit it..
You would be more than a bless for me if you managed to do it! :)
You may want to have a look at my post:
http://lists.nongnu.org/archive/html/qemu-devel/2011-01/msg02361.html
Thank you very much in advance!
Stefano B



reply via email to

[Prev in Thread] Current Thread [Next in Thread]