[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 18/20] elf-loader: Provide the possibility to relocat
From: |
Christian Borntraeger |
Subject: |
[Qemu-devel] [PULL 18/20] elf-loader: Provide the possibility to relocate s390 ELF files |
Date: |
Tue, 10 Mar 2015 09:38:11 +0100 |
From: Thomas Huth <address@hidden>
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>
Message-Id: <address@hidden>
Acked-by: Alexander Graf <address@hidden>
Signed-off-by: Christian Borntraeger <address@hidden>
---
hw/core/loader.c | 2 ++
include/elf.h | 2 ++
include/hw/elf_ops.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 82 insertions(+)
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;
}
--
2.3.0
- [Qemu-devel] [PULL 05/20] s390x/kvm: helper to set the SIGP status in SigpInfo, (continued)
- [Qemu-devel] [PULL 05/20] s390x/kvm: helper to set the SIGP status in SigpInfo, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 08/20] s390x/kvm: SIGP START is only applicable when STOPPED, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 04/20] s390x/kvm: pass the SIGP instruction parameter to the SIGP handler, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 10/20] s390x/kvm: deliver SIGP RESTART directly if stopped, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 02/20] s390x: introduce defines for SIGP condition codes, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 01/20] synchronize Linux headers to 4.0-rc3, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 20/20] s390-ccw: rebuild BIOS, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 11/20] s390x/kvm: enable the new SIGP handling in user space, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 16/20] s390-ccw.img: Allow bigger ramdisk sizes or offsets, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 17/20] s390-ccw.img: Reinitialize guessing on reboot, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 18/20] elf-loader: Provide the possibility to relocate s390 ELF files,
Christian Borntraeger <=
- [Qemu-devel] [PULL 03/20] s390x/kvm: more details for SIGP handler with one destination vcpu, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 09/20] s390x: add function to deliver restart irqs, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 13/20] virtio-s390: Convert to realize(), Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 07/20] s390x/kvm: implement handling of new SIGP orders, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 12/20] virtio-s390: s390_virtio_device_init() can't fail, simplify, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 19/20] s390/bios: Make the s390-ccw.img relocatable, Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 14/20] virtio-ccw: Convert to realize(), Christian Borntraeger, 2015/03/10
- [Qemu-devel] [PULL 15/20] s390x/kvm: passing max memory size to accelerator, Christian Borntraeger, 2015/03/10
- Re: [Qemu-devel] [PULL 00/20] s390x/kvm: Features and fixes for 2.3, Peter Maydell, 2015/03/10