mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 13:47:56 +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
|
* \brief Jump slot entry code for ARM 64-bit platforms
|
||||||
* \author Stefan Kalkowski
|
* \author Sebastian Sumpf
|
||||||
* \date 2019-03-27
|
* \date 2019-04-04
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -14,6 +14,55 @@
|
|||||||
.text
|
.text
|
||||||
.globl _jmp_slot
|
.globl _jmp_slot
|
||||||
.type _jmp_slot,%function
|
.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:
|
_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
|
* \brief ARM 64-bit specific relocations
|
||||||
|
* \author Sebastian Sumpf
|
||||||
* \author Stefan Kalkowski
|
* \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
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
@ -23,15 +24,16 @@ namespace Linker {
|
|||||||
* Relocation types
|
* Relocation types
|
||||||
*/
|
*/
|
||||||
enum Reloc_types {
|
enum Reloc_types {
|
||||||
R_64 = 1, /* add 64 bit symbol value. */
|
R_64 = 257, /* add 64 bit symbol value. */
|
||||||
R_COPY = 5,
|
R_COPY = 1024,
|
||||||
R_GLOB_DAT = 6, /* GOT entry to data address */
|
R_GLOB_DAT = 1025, /* GOT entry to data address */
|
||||||
R_JMPSLOT = 7, /* jump slot */
|
R_JMPSLOT = 1026, /* jump slot */
|
||||||
R_RELATIVE = 8, /* add load addr of shared object */
|
R_RELATIVE = 1027, /* add load addr of shared object */
|
||||||
};
|
};
|
||||||
|
|
||||||
class Reloc_non_plt;
|
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_plt_generic<Elf::Rela, DT_RELA, R_JMPSLOT> Reloc_plt;
|
||||||
typedef Reloc_jmpslot_generic<Elf::Rela, DT_RELA, false> Reloc_jmpslot;
|
typedef Reloc_jmpslot_generic<Elf::Rela, DT_RELA, false> Reloc_jmpslot;
|
||||||
typedef Reloc_bind_now_generic<Elf::Rela, DT_RELA> Reloc_bind_now;
|
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:
|
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:
|
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)
|
: 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(Dependency const &dep, Elf::Rel const *, unsigned long, bool)
|
||||||
: Reloc_non_plt_generic(dep)
|
: 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