mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
ldso: dynamic linking support for ARM 64-bit
* added relocation support * added assembler invocation path for jump slot relocations fixes issue #3260
This commit is contained in:
parent
7dc875e8c7
commit
a8d856fb65
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* \brief Jump slot entry code for ARM 64-bit platforms
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-03-27
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2019-04-04
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -14,6 +14,55 @@
|
||||
.text
|
||||
.globl _jmp_slot
|
||||
.type _jmp_slot,%function
|
||||
|
||||
/*
|
||||
* sp + 0 = &GOT[n + 3]
|
||||
* sp + 8 = return address
|
||||
* x30 = return address
|
||||
* x16 = &GOT[2] // 'jmp_slot'
|
||||
* x17 = '_jmp_slot' (this function)
|
||||
*/
|
||||
_jmp_slot:
|
||||
1: b 1b
|
||||
|
||||
mov x17, sp
|
||||
|
||||
/* save fp, lr */
|
||||
stp x29, x30, [sp, #-16]!
|
||||
|
||||
/* save arguments */
|
||||
stp x0, x1, [sp, #-16]!
|
||||
stp x2, x3, [sp, #-16]!
|
||||
stp x4, x5, [sp, #-16]!
|
||||
stp x6, x7, [sp, #-16]!
|
||||
stp x8, xzr, [sp, #-16]!
|
||||
|
||||
/* GOT[1] = Dependency */
|
||||
ldr x0, [x16, #-8] /* arg 0 */
|
||||
|
||||
/* calculate symbol index from GOT offset (arg 1) */
|
||||
ldr x2, [x17, #0] /* &GOT[n+3] */
|
||||
sub x1, x2, x16 /* GOT offset */
|
||||
sub x1, x1, #8 /* GOT[3] is first entry */
|
||||
|
||||
/* a GOT entry is 8 bytes, therefore index = offset / 8 */
|
||||
lsr x1, x1, #3 /* x1 / 8 */
|
||||
|
||||
bl jmp_slot
|
||||
|
||||
/* address of function to call */
|
||||
mov x17, x0
|
||||
|
||||
/* restore arguments */
|
||||
ldp x8, xzr, [sp], #16
|
||||
ldp x6, x7, [sp], #16
|
||||
ldp x4, x5, [sp], #16
|
||||
ldp x2, x3, [sp], #16
|
||||
ldp x0, x1, [sp], #16
|
||||
|
||||
/* frame pointer */
|
||||
ldp x29, xzr, [sp], #16
|
||||
|
||||
/* restore lr and close frame from plt code */
|
||||
ldp xzr, x30, [sp], #16
|
||||
|
||||
/* call function */
|
||||
br x17
|
||||
|
@ -1,11 +1,12 @@
|
||||
/**
|
||||
* \brief ARM 64-bit specific relocations
|
||||
* \author Sebastian Sumpf
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-10-26
|
||||
* \date 2019-04-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -23,15 +24,16 @@ namespace Linker {
|
||||
* Relocation types
|
||||
*/
|
||||
enum Reloc_types {
|
||||
R_64 = 1, /* add 64 bit symbol value. */
|
||||
R_COPY = 5,
|
||||
R_GLOB_DAT = 6, /* GOT entry to data address */
|
||||
R_JMPSLOT = 7, /* jump slot */
|
||||
R_RELATIVE = 8, /* add load addr of shared object */
|
||||
R_64 = 257, /* add 64 bit symbol value. */
|
||||
R_COPY = 1024,
|
||||
R_GLOB_DAT = 1025, /* GOT entry to data address */
|
||||
R_JMPSLOT = 1026, /* jump slot */
|
||||
R_RELATIVE = 1027, /* add load addr of shared object */
|
||||
};
|
||||
|
||||
class Reloc_non_plt;
|
||||
|
||||
typedef Plt_got_generic<2> Plt_got;
|
||||
typedef Reloc_plt_generic<Elf::Rela, DT_RELA, R_JMPSLOT> Reloc_plt;
|
||||
typedef Reloc_jmpslot_generic<Elf::Rela, DT_RELA, false> Reloc_jmpslot;
|
||||
typedef Reloc_bind_now_generic<Elf::Rela, DT_RELA> Reloc_bind_now;
|
||||
@ -41,28 +43,60 @@ class Linker::Reloc_non_plt : public Reloc_non_plt_generic
|
||||
{
|
||||
private:
|
||||
|
||||
void _relative(Elf::Rela const *, Elf::Addr *)
|
||||
void _relative(Elf::Rela const *rel, Elf::Addr *addr)
|
||||
{
|
||||
error("not implemented yet");
|
||||
*addr = _dep.obj().reloc_base() + rel->addend;
|
||||
}
|
||||
|
||||
void _glob_dat_64(Elf::Rela const *, Elf::Addr *, bool)
|
||||
void _glob_dat_64(Elf::Rela const *rel, Elf::Addr *addr, bool addend)
|
||||
{
|
||||
error("not implemented yet");
|
||||
Elf::Addr reloc_base;
|
||||
Elf::Sym const *sym;
|
||||
|
||||
if (!(sym = lookup_symbol(rel->sym(), _dep, &reloc_base)))
|
||||
return;
|
||||
|
||||
*addr = reloc_base + sym->st_value + (addend ? rel->addend : 0);
|
||||
if (verbose_reloc(_dep))
|
||||
log("GLOB DAT ", addr, " -> ", *addr,
|
||||
" r ", reloc_base, " v ", sym->st_value);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Reloc_non_plt(Dependency const &dep, Elf::Rela const *, unsigned long, bool)
|
||||
Reloc_non_plt(Dependency const &dep, Elf::Rela const *rel, unsigned long size,
|
||||
bool second_pass)
|
||||
: Reloc_non_plt_generic(dep)
|
||||
{
|
||||
error("not implemented yet");
|
||||
Elf::Rela const *end = rel + (size / sizeof(Elf::Rela));
|
||||
|
||||
for (; rel < end; rel++) {
|
||||
Elf::Addr *addr = (Elf::Addr *)(_dep.obj().reloc_base() + rel->offset);
|
||||
|
||||
if (second_pass && rel->type() != R_GLOB_DAT)
|
||||
continue;
|
||||
|
||||
switch(rel->type()) {
|
||||
case R_64:
|
||||
case R_GLOB_DAT: _glob_dat_64(rel, addr, true); break;
|
||||
case R_COPY: _copy<Elf::Rela>(rel, addr); break;
|
||||
case R_RELATIVE: _relative(rel, addr); break;
|
||||
|
||||
default:
|
||||
if (!_dep.obj().is_linker()) {
|
||||
warning("LD: Unkown relocation ", (int)rel->type());
|
||||
throw Incompatible();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reloc_non_plt(Dependency const &dep, Elf::Rel const *, unsigned long, bool)
|
||||
: Reloc_non_plt_generic(dep)
|
||||
{
|
||||
error("not implemented yet");
|
||||
error("LD: DT_REL not supported");
|
||||
throw Incompatible();
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user