ld-elf.so.1 assumed a few too many things about the ordering of sections
produced by ld(8) (ie: that _DYNAMIC immediately follows the _GOT). The new binutils import changed that, and the intial GOT relocation broke. Use a custom linker script to provide a real end-of-GOT symbol. Update ld.so to deal with the new (faster) PLT format that gcc-3.1 and binutils can produce. This is probably incomplete, but appears to be working again. Obtained from: NetBSD (And a fix to a silly mistake that I made by: gallatin)
This commit is contained in:
parent
bf46cf3a97
commit
cc75746718
@ -1 +1,4 @@
|
|||||||
|
# $FreeBSD$
|
||||||
|
|
||||||
CFLAGS+= -mno-fp-regs
|
CFLAGS+= -mno-fp-regs
|
||||||
|
LDFLAGS+= -Wl,--script,${.CURDIR}/alpha/ld.so.script
|
||||||
|
135
libexec/rtld-elf/alpha/ld.so.script
Normal file
135
libexec/rtld-elf/alpha/ld.so.script
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/* $NetBSD: ld.so.script,v 1.2 2001/12/13 20:31:31 thorpej Exp $ */
|
||||||
|
/* $FreeBSD$ */
|
||||||
|
|
||||||
|
OUTPUT_FORMAT("elf64-alpha", "elf64-alpha",
|
||||||
|
"elf64-alpha")
|
||||||
|
OUTPUT_ARCH(alpha)
|
||||||
|
ENTRY(__start)
|
||||||
|
/* SEARCH_DIR(/usr/lib); JRT */
|
||||||
|
/* Do we need any of these for elf?
|
||||||
|
__DYNAMIC = 0; */
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Read-only sections, merged into text segment: */
|
||||||
|
. = 0 + SIZEOF_HEADERS;
|
||||||
|
.hash : { *(.hash) }
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
.gnu.version : { *(.gnu.version) }
|
||||||
|
.gnu.version_d : { *(.gnu.version_d) }
|
||||||
|
.gnu.version_r : { *(.gnu.version_r) }
|
||||||
|
.rel.text :
|
||||||
|
{ *(.rel.text) *(.rel.gnu.linkonce.t*) }
|
||||||
|
.rela.text :
|
||||||
|
{ *(.rela.text) *(.rela.gnu.linkonce.t*) }
|
||||||
|
.rel.data :
|
||||||
|
{ *(.rel.data) *(.rel.gnu.linkonce.d*) }
|
||||||
|
.rela.data :
|
||||||
|
{ *(.rela.data) *(.rela.gnu.linkonce.d*) }
|
||||||
|
.rel.rodata :
|
||||||
|
{ *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
|
||||||
|
.rela.rodata :
|
||||||
|
{ *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
|
||||||
|
.rel.got : { *(.rel.got) }
|
||||||
|
.rela.got : { *(.rela.got) }
|
||||||
|
.rel.ctors : { *(.rel.ctors) }
|
||||||
|
.rela.ctors : { *(.rela.ctors) }
|
||||||
|
.rel.dtors : { *(.rel.dtors) }
|
||||||
|
.rela.dtors : { *(.rela.dtors) }
|
||||||
|
.rel.init : { *(.rel.init) }
|
||||||
|
.rela.init : { *(.rela.init) }
|
||||||
|
.rel.fini : { *(.rel.fini) }
|
||||||
|
.rela.fini : { *(.rela.fini) }
|
||||||
|
.rel.bss : { *(.rel.bss) }
|
||||||
|
.rela.bss : { *(.rela.bss) }
|
||||||
|
.rel.plt : { *(.rel.plt) }
|
||||||
|
.rela.plt : { *(.rela.plt) }
|
||||||
|
.init : { *(.init) } =0x47ff041f
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
*(.stub)
|
||||||
|
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
*(.gnu.linkonce.t*)
|
||||||
|
} =0x47ff041f
|
||||||
|
_etext = .;
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
.fini : { *(.fini) } =0x47ff041f
|
||||||
|
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.reginfo : { *(.reginfo) }
|
||||||
|
/* Adjust the address for the data segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = ALIGN(0x100000) + (. & (0x100000 - 1));
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
*(.gnu.linkonce.d*)
|
||||||
|
CONSTRUCTORS
|
||||||
|
}
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
*(.ctors)
|
||||||
|
}
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
*(.dtors)
|
||||||
|
}
|
||||||
|
.plt : { *(.plt) }
|
||||||
|
.got : { *(.got.plt) *(.got) }
|
||||||
|
PROVIDE (_GOT_END_ = .);
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
/* We want the small data sections together, so single-instruction offsets
|
||||||
|
can access them all, and initialized data all before uninitialized, so
|
||||||
|
we can shorten the on-disk segment size. */
|
||||||
|
.sdata : { *(.sdata) }
|
||||||
|
_edata = .;
|
||||||
|
PROVIDE (edata = .);
|
||||||
|
__bss_start = .;
|
||||||
|
.sbss : { *(.sbss) *(.scommon) }
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss)
|
||||||
|
*(COMMON)
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
_end = . ;
|
||||||
|
PROVIDE (end = .);
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
/* These must appear regardless of . */
|
||||||
|
}
|
@ -47,7 +47,7 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "rtld.h"
|
#include "rtld.h"
|
||||||
|
|
||||||
extern Elf_Dyn _DYNAMIC;
|
extern Elf_Dyn _GOT_END_;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros for loading/storing unaligned 64-bit values. These are
|
* Macros for loading/storing unaligned 64-bit values. These are
|
||||||
@ -111,7 +111,7 @@ reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
|
|||||||
case R_ALPHA_RELATIVE: {
|
case R_ALPHA_RELATIVE: {
|
||||||
if (obj != obj_rtld ||
|
if (obj != obj_rtld ||
|
||||||
(caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
|
(caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
|
||||||
(caddr_t)where >= (caddr_t)&_DYNAMIC)
|
(caddr_t)where >= (caddr_t)&_GOT_END_)
|
||||||
store64(where,
|
store64(where,
|
||||||
load64(where) + (Elf_Addr) obj->relocbase);
|
load64(where) + (Elf_Addr) obj->relocbase);
|
||||||
}
|
}
|
||||||
@ -476,10 +476,20 @@ do_copy_relocations(Obj_Entry *dstobj)
|
|||||||
void
|
void
|
||||||
init_pltgot(Obj_Entry *obj)
|
init_pltgot(Obj_Entry *obj)
|
||||||
{
|
{
|
||||||
|
u_int32_t *pltgot;
|
||||||
|
|
||||||
if (obj->pltgot != NULL &&
|
if (obj->pltgot != NULL &&
|
||||||
(obj->pltrelsize != 0 || obj->pltrelasize != 0)) {
|
(obj->pltrelsize != 0 || obj->pltrelasize != 0)) {
|
||||||
/* This function will be called to perform the relocation. */
|
/*
|
||||||
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
|
* This function will be called to perform the relocation.
|
||||||
|
* Look for the ldah instruction from the old PLT format since
|
||||||
|
* that will tell us what format we are trying to relocate.
|
||||||
|
*/
|
||||||
|
pltgot = (u_int32_t *) obj->pltgot;
|
||||||
|
if ((pltgot[8] & 0xffff0000) == 0x279f0000)
|
||||||
|
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start_old;
|
||||||
|
else
|
||||||
|
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
|
||||||
/* Identify this shared object */
|
/* Identify this shared object */
|
||||||
obj->pltgot[3] = (Elf_Addr) obj;
|
obj->pltgot[3] = (Elf_Addr) obj;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,9 @@ Elf_Addr reloc_jmpslot(Elf_Addr *, Elf_Addr,
|
|||||||
#define call_initfini_pointer(obj, target) \
|
#define call_initfini_pointer(obj, target) \
|
||||||
(((InitFunc)(target))())
|
(((InitFunc)(target))())
|
||||||
|
|
||||||
|
/* Lazy binding entry point, called via PLT. */
|
||||||
|
void _rtld_bind_start_old(void);
|
||||||
|
|
||||||
/* Atomic operations. */
|
/* Atomic operations. */
|
||||||
int cmp0_and_store_int(volatile int *, int);
|
int cmp0_and_store_int(volatile int *, int);
|
||||||
void atomic_add_int(volatile int *, int);
|
void atomic_add_int(volatile int *, int);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <machine/pal.h>
|
#include <machine/pal.h>
|
||||||
|
|
||||||
.extern _GLOBAL_OFFSET_TABLE_
|
.extern _GLOBAL_OFFSET_TABLE_
|
||||||
|
.extern _GOT_END_
|
||||||
|
|
||||||
LEAF(_rtld_start, 0) /* XXX */
|
LEAF(_rtld_start, 0) /* XXX */
|
||||||
.set noreorder
|
.set noreorder
|
||||||
@ -58,7 +59,7 @@ $34: ldiq t3, $34 /* get where the linker thought we were */
|
|||||||
|
|
||||||
lda t5, _GLOBAL_OFFSET_TABLE_
|
lda t5, _GLOBAL_OFFSET_TABLE_
|
||||||
addq t8, t5, t9 /* add the displacement */
|
addq t8, t5, t9 /* add the displacement */
|
||||||
lda t4, _DYNAMIC
|
lda t4, _GOT_END_
|
||||||
addq t8, t4, t10 /* add the displacement */
|
addq t8, t4, t10 /* add the displacement */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -87,7 +88,7 @@ $35: ldq t1, 0(t9) /* load the value */
|
|||||||
lda sp, 16(sp) /* readjust our stack */
|
lda sp, 16(sp) /* readjust our stack */
|
||||||
mov s0, a0 /* stack pointer */
|
mov s0, a0 /* stack pointer */
|
||||||
mov s1, a3 /* ps_strings pointer */
|
mov s1, a3 /* ps_strings pointer */
|
||||||
mov v0, t12
|
mov v0, pv
|
||||||
jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj); */
|
jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj); */
|
||||||
ldgp gp, 0(ra)
|
ldgp gp, 0(ra)
|
||||||
|
|
||||||
@ -95,77 +96,118 @@ $35: ldq t1, 0(t9) /* load the value */
|
|||||||
halt
|
halt
|
||||||
END(_rtld_start)
|
END(_rtld_start)
|
||||||
|
|
||||||
.set noat
|
#define RTLD_BIND_START_PROLOGUE \
|
||||||
.globl _rtld_bind_start
|
/* at_reg already used by PLT code. */ \
|
||||||
.ent _rtld_bind_start
|
.set noat ; \
|
||||||
_rtld_bind_start:
|
\
|
||||||
|
/* \
|
||||||
|
* Allocate stack frame and preserve all registers that the \
|
||||||
|
* caller would have normally saved themselves. \
|
||||||
|
*/ \
|
||||||
|
lda sp, -168(sp) ; \
|
||||||
|
stq ra, 0(sp) ; \
|
||||||
|
stq v0, 8(sp) ; \
|
||||||
|
stq t0, 16(sp) ; \
|
||||||
|
stq t1, 24(sp) ; \
|
||||||
|
stq t2, 32(sp) ; \
|
||||||
|
stq t3, 40(sp) ; \
|
||||||
|
stq t4, 48(sp) ; \
|
||||||
|
stq t5, 56(sp) ; \
|
||||||
|
stq t6, 64(sp) ; \
|
||||||
|
stq t7, 72(sp) ; \
|
||||||
|
stq a0, 80(sp) ; \
|
||||||
|
stq a1, 88(sp) ; \
|
||||||
|
stq a2, 96(sp) ; \
|
||||||
|
stq a3, 104(sp) ; \
|
||||||
|
stq a4, 112(sp) ; \
|
||||||
|
stq a5, 120(sp) ; \
|
||||||
|
stq t8, 128(sp) ; \
|
||||||
|
stq t9, 136(sp) ; \
|
||||||
|
stq t10, 144(sp) ; \
|
||||||
|
stq t11, 152(sp) ; \
|
||||||
|
stq gp, 160(sp) ; \
|
||||||
|
\
|
||||||
|
/* \
|
||||||
|
* Load our global pointer. Note, can't use pv, since it is \
|
||||||
|
* already used by the PLT code. \
|
||||||
|
*/ \
|
||||||
|
br t0, 1f ; \
|
||||||
|
1: LDGP(t0)
|
||||||
|
|
||||||
|
#define RTLD_BIND_START_EPILOGUE \
|
||||||
|
/* Move the destination address into position. */ \
|
||||||
|
mov v0, pv ; \
|
||||||
|
\
|
||||||
|
/* Restore program registers. */ \
|
||||||
|
ldq ra, 0(sp) ; \
|
||||||
|
ldq v0, 8(sp) ; \
|
||||||
|
ldq t0, 16(sp) ; \
|
||||||
|
ldq t1, 24(sp) ; \
|
||||||
|
ldq t2, 32(sp) ; \
|
||||||
|
ldq t3, 40(sp) ; \
|
||||||
|
ldq t4, 48(sp) ; \
|
||||||
|
ldq t5, 56(sp) ; \
|
||||||
|
ldq t6, 64(sp) ; \
|
||||||
|
ldq t7, 72(sp) ; \
|
||||||
|
ldq a0, 80(sp) ; \
|
||||||
|
ldq a1, 88(sp) ; \
|
||||||
|
ldq a2, 96(sp) ; \
|
||||||
|
ldq a3, 104(sp) ; \
|
||||||
|
ldq a4, 112(sp) ; \
|
||||||
|
ldq a5, 120(sp) ; \
|
||||||
|
ldq t8, 128(sp) ; \
|
||||||
|
ldq t9, 136(sp) ; \
|
||||||
|
ldq t10, 144(sp) ; \
|
||||||
|
ldq t11, 152(sp) ; \
|
||||||
|
ldq gp, 160(sp) ; \
|
||||||
|
/* XXX LDGP? */ \
|
||||||
|
\
|
||||||
|
/* \
|
||||||
|
* We've patched the PLT; sync the I-stream. \
|
||||||
|
*/ \
|
||||||
|
imb ; \
|
||||||
|
\
|
||||||
|
/* Pop the stack frame and turn control to the destination. */ \
|
||||||
|
lda sp, 168(sp) ; \
|
||||||
|
jmp zero, (pv)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lazy binding entry point, called via PLT.
|
||||||
|
*/
|
||||||
|
NESTED_NOPROFILE(_rtld_bind_start, 0, 168, ra, 0, 0)
|
||||||
|
|
||||||
|
RTLD_BIND_START_PROLOGUE
|
||||||
|
|
||||||
lda sp, -168(sp)
|
|
||||||
.frame sp, 168, $26
|
|
||||||
/* Preserve all registers that C normally doesn't. */
|
|
||||||
stq $26, 0(sp)
|
|
||||||
stq $0, 8(sp)
|
|
||||||
stq $1, 16(sp)
|
|
||||||
stq $2, 24(sp)
|
|
||||||
stq $3, 32(sp)
|
|
||||||
stq $4, 40(sp)
|
|
||||||
stq $5, 48(sp)
|
|
||||||
stq $6, 56(sp)
|
|
||||||
stq $7, 64(sp)
|
|
||||||
stq $8, 72(sp)
|
|
||||||
stq $16, 80(sp)
|
|
||||||
stq $17, 88(sp)
|
|
||||||
stq $18, 96(sp)
|
|
||||||
stq $19, 104(sp)
|
|
||||||
stq $20, 112(sp)
|
|
||||||
stq $21, 120(sp)
|
|
||||||
stq $22, 128(sp)
|
|
||||||
stq $23, 136(sp)
|
|
||||||
stq $24, 144(sp)
|
|
||||||
stq $25, 152(sp)
|
|
||||||
stq $29, 160(sp)
|
|
||||||
.mask 0x27ff01ff, -168
|
|
||||||
/* Set up our $gp */
|
|
||||||
br gp, $100
|
|
||||||
$100: ldgp gp, 0(gp)
|
|
||||||
.prologue 1
|
|
||||||
/* Set up the arguments for _rtld_bind. */
|
/* Set up the arguments for _rtld_bind. */
|
||||||
subq at_reg, t12, a1 /* calculate reloc offset */
|
subq at_reg, pv, a1 /* calculate reloc offset */
|
||||||
ldq a0, 8(t12) /* object structure */
|
ldq a0, 8(pv) /* object structure */
|
||||||
subq a1, 20, a1 /* = (at - t11 - 20) / 12 * 24 */
|
subq a1, 20, a1 /* = (at - t11 - 20) / 12 * 24 */
|
||||||
addq a1, a1, a1
|
addq a1, a1, a1
|
||||||
|
|
||||||
CALL(_rtld_bind)
|
CALL(_rtld_bind)
|
||||||
|
|
||||||
/* Move the destination address into position. */
|
RTLD_BIND_START_EPILOGUE
|
||||||
mov $0, $27
|
|
||||||
/* Restore program registers. */
|
END(_rtld_bind_start)
|
||||||
ldq $26, 0(sp)
|
|
||||||
ldq $0, 8(sp)
|
/*
|
||||||
ldq $1, 16(sp)
|
* Lazy binding entry point, called via PLT. This version is for the
|
||||||
ldq $2, 24(sp)
|
* old PLT entry format.
|
||||||
ldq $3, 32(sp)
|
*/
|
||||||
ldq $4, 40(sp)
|
NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0)
|
||||||
ldq $5, 48(sp)
|
|
||||||
ldq $6, 56(sp)
|
RTLD_BIND_START_PROLOGUE
|
||||||
ldq $7, 64(sp)
|
|
||||||
ldq $8, 72(sp)
|
/* Set up the arguments for _rtld_bind. */
|
||||||
ldq $16, 80(sp)
|
ldq a0, 8(pv) /* object structure */
|
||||||
ldq $17, 88(sp)
|
mov at_reg, a1 /* offset of reloc entry */
|
||||||
ldq $18, 96(sp)
|
|
||||||
ldq $19, 104(sp)
|
CALL(_rtld_bind)
|
||||||
ldq $20, 112(sp)
|
|
||||||
ldq $21, 120(sp)
|
RTLD_BIND_START_EPILOGUE
|
||||||
ldq $22, 128(sp)
|
|
||||||
ldq $23, 136(sp)
|
END(_rtld_bind_start_old)
|
||||||
ldq $24, 144(sp)
|
|
||||||
ldq $25, 152(sp)
|
|
||||||
ldq $29, 160(sp)
|
|
||||||
/* Flush the Icache after having modified the .plt code. */
|
|
||||||
imb
|
|
||||||
/* Clean up and turn control to the destination */
|
|
||||||
lda sp, 168(sp)
|
|
||||||
jmp $31, ($27)
|
|
||||||
.end _rtld_bind_start
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* int cmp0_and_store_int(volatile int *p, int newval);
|
* int cmp0_and_store_int(volatile int *p, int newval);
|
||||||
|
Loading…
Reference in New Issue
Block a user