qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to r


From: Thomas Huth
Subject: Re: [Qemu-devel] [PATCH v2 1/2] elf-loader: Provide the possibility to relocate s390 ELF files
Date: Mon, 9 Mar 2015 14:30:05 +0100

On Mon, 09 Mar 2015 12:11:49 +0100
Christian Borntraeger <address@hidden> wrote:

> Am 09.03.2015 um 11:12 schrieb Thomas Huth:
> > On s390, we would like to load our "BIOS" s390-ccw.img to the end of the
> > RAM. Therefor we need the possibility to relocate the ELF file so that
> > it can also run from different addresses. This patch adds the necessary
> > code to the QEMU ELF loader function.
> > 
> > Signed-off-by: Thomas Huth <address@hidden>
> 
> I think this was Acked by Alex?

Well, that was on the first version which still had endianess bugs ...
Alex, does your Ack still stand for v2, too?

 Thomas


> > ---
> >  hw/core/loader.c     |    2 +
> >  include/elf.h        |    2 +
> >  include/hw/elf_ops.h |   78 
> > ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 82 insertions(+), 0 deletions(-)
> > 
> > diff --git a/hw/core/loader.c b/hw/core/loader.c
> > index e45dc0b..76d8aca 100644
> > --- a/hw/core/loader.c
> > +++ b/hw/core/loader.c
> > @@ -297,6 +297,7 @@ static void *load_at(int fd, int offset, int size)
> >  #undef elf_phdr
> >  #undef elf_shdr
> >  #undef elf_sym
> > +#undef elf_rela
> >  #undef elf_note
> >  #undef elf_word
> >  #undef elf_sword
> > @@ -307,6 +308,7 @@ static void *load_at(int fd, int offset, int size)
> >  #define elf_note   elf64_note
> >  #define elf_shdr   elf64_shdr
> >  #define elf_sym            elf64_sym
> > +#define elf_rela        elf64_rela
> >  #define elf_word        uint64_t
> >  #define elf_sword        int64_t
> >  #define bswapSZs   bswap64s
> > diff --git a/include/elf.h b/include/elf.h
> > index a516584..3e75f05 100644
> > --- a/include/elf.h
> > +++ b/include/elf.h
> > @@ -1508,6 +1508,7 @@ struct elf32_fdpic_loadmap {
> >  #define elf_shdr   elf32_shdr
> >  #define elf_sym            elf32_sym
> >  #define elf_addr_t Elf32_Off
> > +#define elf_rela  elf32_rela
> > 
> >  #ifdef ELF_USES_RELOCA
> >  # define ELF_RELOC      Elf32_Rela
> > @@ -1523,6 +1524,7 @@ struct elf32_fdpic_loadmap {
> >  #define elf_shdr   elf64_shdr
> >  #define elf_sym            elf64_sym
> >  #define elf_addr_t Elf64_Off
> > +#define elf_rela  elf64_rela
> > 
> >  #ifdef ELF_USES_RELOCA
> >  # define ELF_RELOC      Elf64_Rela
> > diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
> > index a517753..16a627b 100644
> > --- a/include/hw/elf_ops.h
> > +++ b/include/hw/elf_ops.h
> > @@ -49,6 +49,13 @@ static void glue(bswap_sym, SZ)(struct elf_sym *sym)
> >      bswap16s(&sym->st_shndx);
> >  }
> > 
> > +static void glue(bswap_rela, SZ)(struct elf_rela *rela)
> > +{
> > +    bswapSZs(&rela->r_offset);
> > +    bswapSZs(&rela->r_info);
> > +    bswapSZs((elf_word *)&rela->r_addend);
> > +}
> > +
> >  static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table,
> >                                                 int n, int type)
> >  {
> > @@ -182,6 +189,75 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, 
> > int fd, int must_swab,
> >      return -1;
> >  }
> > 
> > +static int glue(elf_reloc, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
> > +                               uint64_t (*translate_fn)(void *, uint64_t),
> > +                               void *translate_opaque, uint8_t *data,
> > +                               struct elf_phdr *ph, int elf_machine)
> > +{
> > +    struct elf_shdr *reltab, *shdr_table = NULL;
> > +    struct elf_rela *rels = NULL;
> > +    int nrels, i, ret = -1;
> > +    elf_word wordval;
> > +    void *addr;
> > +
> > +    shdr_table = load_at(fd, ehdr->e_shoff,
> > +                         sizeof(struct elf_shdr) * ehdr->e_shnum);
> > +    if (!shdr_table) {
> > +        return -1;
> > +    }
> > +    if (must_swab) {
> > +        for (i = 0; i < ehdr->e_shnum; i++) {
> > +            glue(bswap_shdr, SZ)(&shdr_table[i]);
> > +        }
> > +    }
> > +
> > +    reltab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_RELA);
> > +    if (!reltab) {
> > +        goto fail;
> > +    }
> > +    rels = load_at(fd, reltab->sh_offset, reltab->sh_size);
> > +    if (!rels) {
> > +        goto fail;
> > +    }
> > +    nrels = reltab->sh_size / sizeof(struct elf_rela);
> > +
> > +    for (i = 0; i < nrels; i++) {
> > +        if (must_swab) {
> > +            glue(bswap_rela, SZ)(&rels[i]);
> > +        }
> > +        if (rels[i].r_offset < ph->p_vaddr ||
> > +            rels[i].r_offset >= ph->p_vaddr + ph->p_filesz) {
> > +            continue;
> > +        }
> > +        addr = &data[rels[i].r_offset - ph->p_vaddr];
> > +        switch (elf_machine) {
> > +        case EM_S390:
> > +            switch (rels[i].r_info) {
> > +            case R_390_RELATIVE:
> > +                wordval = *(elf_word *)addr;
> > +                if (must_swab) {
> > +                    bswapSZs(&wordval);
> > +                }
> > +                wordval = translate_fn(translate_opaque, wordval);
> > +                if (must_swab) {
> > +                    bswapSZs(&wordval);
> > +                }
> > +                *(elf_word *)addr = wordval;
> > +                break;
> > +            default:
> > +                fprintf(stderr, "Unsupported relocation type %i!\n",
> > +                        (int)rels[i].r_info);
> > +            }
> > +        }
> > +    }
> > +
> > +    ret = 0;
> > +fail:
> > +    g_free(rels);
> > +    g_free(shdr_table);
> > +    return ret;
> > +}
> > +
> >  static int glue(load_elf, SZ)(const char *name, int fd,
> >                                uint64_t (*translate_fn)(void *, uint64_t),
> >                                void *translate_opaque,
> > @@ -271,6 +347,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
> >                 linked at the wrong physical address.  */
> >              if (translate_fn) {
> >                  addr = translate_fn(translate_opaque, ph->p_paddr);
> > +                glue(elf_reloc, SZ)(&ehdr, fd, must_swab,  translate_fn,
> > +                                    translate_opaque, data, ph, 
> > elf_machine);
> >              } else {
> >                  addr = ph->p_paddr;
> >              }
> > 
> 




reply via email to

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