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
{
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, unsigned JMPSLOT> struct Reloc_plt_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
* 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)
log("OBJ: ", dep.obj().name(), " (", &dep, ")");
pltgot[1] = (Elf::Addr) &dep; /* ELF object */
pltgot[2] = (Elf::Addr) &_jmp_slot; /* Linker entry */
pltgot[1] = (Elf::Addr) &dep; /* ELF object */
pltgot[JUMP_INDEX] = (Elf::Addr) &_jmp_slot; /* Linker entry */
}
};

View File

@ -29,6 +29,7 @@ namespace Linker {
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_jmpslot_generic<Elf::Rel, DT_REL, false> Reloc_jmpslot;
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
* under the terms of the GNU Affero General Public License version 3.
@ -15,9 +15,49 @@
.globl _jmp_slot
.type _jmp_slot,%function
/*
* stack[0] = RA
* ip = &GOT[n+3]
* lr = &GOT[2]
* t0 = GOT[1] = Dependency
* t1 = PLT offset
*/
_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;
typedef Plt_got_generic<0> 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;
@ -87,9 +88,9 @@ class Linker::Reloc_non_plt : public Reloc_non_plt_generic
log("LD: reloc: ", rel, " type: ", (int)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_RELATIVE: _relative(rel, addr); break;
case R_JMPSLOT: break;
default:
if (!_dep.obj().is_linker()) {

View File

@ -29,6 +29,7 @@ namespace Linker {
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_jmpslot_generic<Elf::Rel, DT_REL, true> Reloc_jmpslot;
typedef Reloc_bind_now_generic<Elf::Rel, DT_REL> Reloc_bind_now;

View File

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