mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
elf-loader: Provide the possibility to relocate s390 ELF files
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 <thuth@linux.vnet.ibm.com> Message-Id: <1425895973-15239-2-git-send-email-thuth@linux.vnet.ibm.com> Acked-by: Alexander Graf <agraf@suse.de> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
This commit is contained in:
parent
5c8d542004
commit
5dce07e1cb
3 changed files with 82 additions and 0 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue