Commit 1af02e83 authored by Mike Frysinger's avatar Mike Frysinger Committed by Riku Voipio
Browse files

linux-user/elfload: add FDPIC support

parent 73160d95
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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

+71 −0
Original line number Diff line number Diff line
@@ -1075,6 +1075,33 @@ 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 */
    n = info->nsegs;
    while (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 +1114,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 +1239,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 +1257,9 @@ static void load_elf_image(const char *image_name, int image_fd,
            if (a > hiaddr) {
                hiaddr = a;
            }
#ifdef CONFIG_USE_FDPIC
            ++info->nsegs;
#endif
        }
    }

@@ -1290,6 +1340,27 @@ 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) {
            switch (phdr[i].p_type) {
            case PT_DYNAMIC:
                info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias;
                break;
            case PT_LOAD:
                loadsegs->addr = phdr[i].p_vaddr + load_bias;
                loadsegs->p_vaddr = phdr[i].p_vaddr;
                loadsegs->p_memsz = phdr[i].p_memsz;
                ++loadsegs;
                break;
            }
        }
    }
#endif

    info->load_bias = load_bias;
    info->load_addr = load_addr;
    info->entry = ehdr->e_entry + load_bias;
+7 −0
Original line number Diff line number Diff line
@@ -51,6 +51,13 @@ struct image_info {
        abi_ulong       arg_start;
        abi_ulong       arg_end;
	int		personality;
#ifdef CONFIG_USE_FDPIC
        abi_ulong       loadmap_addr;
        uint16_t        nsegs;
        void           *loadsegs;
        abi_ulong       pt_dynamic_addr;
        struct image_info *other_info;
#endif
};

#ifdef TARGET_I386