ldso: lazy binding support for RISC-V

* added assembler invocation path for jump slot relocations
* fix GOT initialization (jmp_slot pointer goes to GOT[0] not GOT[2] on
  RISC-V)

Fixes #3339
This commit is contained in:
Sebastian Sumpf 2019-05-08 15:01:21 +02:00 committed by Christian Helmuth
parent 4f0b17a4dc
commit 467b96abf4
6 changed files with 55 additions and 11 deletions

View File

@ -31,7 +31,7 @@ extern "C" void _jmp_slot(void);
namespace Linker namespace Linker
{ {
struct Plt_got; template <unsigned JUMP_INDEX = 2> struct Plt_got_generic;
template <typename REL, unsigned TYPE, bool DIV> class Reloc_jmpslot_generic; template <typename REL, unsigned TYPE, bool DIV> class Reloc_jmpslot_generic;
template <typename REL, unsigned TYPE, unsigned JMPSLOT> struct Reloc_plt_generic; template <typename REL, unsigned TYPE, unsigned JMPSLOT> struct Reloc_plt_generic;
template <typename REL, unsigned TYPE> struct Reloc_bind_now_generic; template <typename REL, unsigned TYPE> struct Reloc_bind_now_generic;
@ -43,15 +43,15 @@ namespace Linker
* Set 2nd and 3rd GOT entry (see: SYSTEM V APPLICATION BINARY INTERFACE * Set 2nd and 3rd GOT entry (see: SYSTEM V APPLICATION BINARY INTERFACE
* Intel386 Architecture Processor Supplement - 5.9 * Intel386 Architecture Processor Supplement - 5.9
*/ */
struct Linker::Plt_got template <unsigned JUMP_INDEX> struct Linker::Plt_got_generic
{ {
Plt_got(Dependency const &dep, Elf::Addr *pltgot) Plt_got_generic(Dependency const &dep, Elf::Addr *pltgot)
{ {
if (verbose_relocation) if (verbose_relocation)
log("OBJ: ", dep.obj().name(), " (", &dep, ")"); log("OBJ: ", dep.obj().name(), " (", &dep, ")");
pltgot[1] = (Elf::Addr) &dep; /* ELF object */ pltgot[1] = (Elf::Addr) &dep; /* ELF object */
pltgot[2] = (Elf::Addr) &_jmp_slot; /* Linker entry */ pltgot[JUMP_INDEX] = (Elf::Addr) &_jmp_slot; /* Linker entry */
} }
}; };

View File

@ -29,6 +29,7 @@ namespace Linker {
class Reloc_non_plt; class Reloc_non_plt;
typedef Plt_got_generic<2> Plt_got;
typedef Reloc_plt_generic<Elf::Rel, DT_REL, R_JMPSLOT> Reloc_plt; typedef Reloc_plt_generic<Elf::Rel, DT_REL, R_JMPSLOT> Reloc_plt;
typedef Reloc_jmpslot_generic<Elf::Rel, DT_REL, false> Reloc_jmpslot; typedef Reloc_jmpslot_generic<Elf::Rel, DT_REL, false> Reloc_jmpslot;
typedef Reloc_bind_now_generic<Elf::Rel, DT_REL> Reloc_bind_now; typedef Reloc_bind_now_generic<Elf::Rel, DT_REL> Reloc_bind_now;

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2015-2017 Genode Labs GmbH * Copyright (C) 2015-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.
@ -15,9 +15,49 @@
.globl _jmp_slot .globl _jmp_slot
.type _jmp_slot,%function .type _jmp_slot,%function
/* /*
* stack[0] = RA * t0 = GOT[1] = Dependency
* ip = &GOT[n+3] * t1 = PLT offset
* lr = &GOT[2]
*/ */
_jmp_slot: _jmp_slot:
jal jmp_slot
/* stack frame */
addi sp, sp, -(8*9)
/* save arguments and return address */
sd a0, (0)(sp)
sd a1, (1 * 8)(sp)
sd a2, (2 * 8)(sp)
sd a3, (3 * 8)(sp)
sd a4, (4 * 8)(sp)
sd a5, (5 * 8)(sp)
sd a6, (6 * 8)(sp)
sd a7, (7 * 8)(sp)
sd ra, (8 * 8)(sp)
/* GOT[1] = Dependency */
mv a0, t0 /* arg 0 */
/* calculate symbol index from PLT offset (index = offset / 8) */
srli a1, t1, 3 /* arg 1 */
jal jmp_slot
/* save address of function to call */
mv t0, a0
/* restore arguments and return address */
ld a0, (0)(sp)
ld a1, (1 * 8)(sp)
ld a2, (2 * 8)(sp)
ld a3, (3 * 8)(sp)
ld a4, (4 * 8)(sp)
ld a5, (5 * 8)(sp)
ld a6, (6 * 8)(sp)
ld a7, (7 * 8)(sp)
ld ra, (8 * 8)(sp)
/* stack frame */
addi sp, sp,(8*9)
/* call function */
jr t0

View File

@ -38,6 +38,7 @@ namespace Linker {
class Reloc_non_plt; class Reloc_non_plt;
typedef Plt_got_generic<0> 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;
@ -87,9 +88,9 @@ class Linker::Reloc_non_plt : public Reloc_non_plt_generic
log("LD: reloc: ", rel, " type: ", (int)rel->type()); log("LD: reloc: ", rel, " type: ", (int)rel->type());
switch(rel->type()) { switch(rel->type()) {
case R_JMPSLOT: _glob_dat_64(rel, addr, false); break;
case R_64: _glob_dat_64(rel, addr, true); break; case R_64: _glob_dat_64(rel, addr, true); break;
case R_RELATIVE: _relative(rel, addr); break; case R_RELATIVE: _relative(rel, addr); break;
case R_JMPSLOT: break;
default: default:
if (!_dep.obj().is_linker()) { if (!_dep.obj().is_linker()) {

View File

@ -29,6 +29,7 @@ namespace Linker {
class Reloc_non_plt; class Reloc_non_plt;
typedef Plt_got_generic<2> Plt_got;
typedef Reloc_plt_generic<Elf::Rel, DT_REL, R_JMPSLOT> Reloc_plt; typedef Reloc_plt_generic<Elf::Rel, DT_REL, R_JMPSLOT> Reloc_plt;
typedef Reloc_jmpslot_generic<Elf::Rel, DT_REL, true> Reloc_jmpslot; typedef Reloc_jmpslot_generic<Elf::Rel, DT_REL, true> Reloc_jmpslot;
typedef Reloc_bind_now_generic<Elf::Rel, DT_REL> Reloc_bind_now; typedef Reloc_bind_now_generic<Elf::Rel, DT_REL> Reloc_bind_now;

View File

@ -32,6 +32,7 @@ namespace Linker {
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;