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
39e37e7212
commit
939bc65715
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=90826
@ -1 +1,4 @@
|
||||
# $FreeBSD$
|
||||
|
||||
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 "rtld.h"
|
||||
|
||||
extern Elf_Dyn _DYNAMIC;
|
||||
extern Elf_Dyn _GOT_END_;
|
||||
|
||||
/*
|
||||
* 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: {
|
||||
if (obj != obj_rtld ||
|
||||
(caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
|
||||
(caddr_t)where >= (caddr_t)&_DYNAMIC)
|
||||
(caddr_t)where >= (caddr_t)&_GOT_END_)
|
||||
store64(where,
|
||||
load64(where) + (Elf_Addr) obj->relocbase);
|
||||
}
|
||||
@ -476,10 +476,20 @@ do_copy_relocations(Obj_Entry *dstobj)
|
||||
void
|
||||
init_pltgot(Obj_Entry *obj)
|
||||
{
|
||||
u_int32_t *pltgot;
|
||||
|
||||
if (obj->pltgot != NULL &&
|
||||
(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 */
|
||||
obj->pltgot[3] = (Elf_Addr) obj;
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ Elf_Addr reloc_jmpslot(Elf_Addr *, Elf_Addr,
|
||||
#define call_initfini_pointer(obj, target) \
|
||||
(((InitFunc)(target))())
|
||||
|
||||
/* Lazy binding entry point, called via PLT. */
|
||||
void _rtld_bind_start_old(void);
|
||||
|
||||
/* Atomic operations. */
|
||||
int cmp0_and_store_int(volatile int *, int);
|
||||
void atomic_add_int(volatile int *, int);
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <machine/pal.h>
|
||||
|
||||
.extern _GLOBAL_OFFSET_TABLE_
|
||||
.extern _GOT_END_
|
||||
|
||||
LEAF(_rtld_start, 0) /* XXX */
|
||||
.set noreorder
|
||||
@ -58,7 +59,7 @@ $34: ldiq t3, $34 /* get where the linker thought we were */
|
||||
|
||||
lda t5, _GLOBAL_OFFSET_TABLE_
|
||||
addq t8, t5, t9 /* add the displacement */
|
||||
lda t4, _DYNAMIC
|
||||
lda t4, _GOT_END_
|
||||
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 */
|
||||
mov s0, a0 /* stack pointer */
|
||||
mov s1, a3 /* ps_strings pointer */
|
||||
mov v0, t12
|
||||
mov v0, pv
|
||||
jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj); */
|
||||
ldgp gp, 0(ra)
|
||||
|
||||
@ -95,77 +96,118 @@ $35: ldq t1, 0(t9) /* load the value */
|
||||
halt
|
||||
END(_rtld_start)
|
||||
|
||||
.set noat
|
||||
.globl _rtld_bind_start
|
||||
.ent _rtld_bind_start
|
||||
_rtld_bind_start:
|
||||
#define RTLD_BIND_START_PROLOGUE \
|
||||
/* at_reg already used by PLT code. */ \
|
||||
.set noat ; \
|
||||
\
|
||||
/* \
|
||||
* 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. */
|
||||
subq at_reg, t12, a1 /* calculate reloc offset */
|
||||
ldq a0, 8(t12) /* object structure */
|
||||
subq at_reg, pv, a1 /* calculate reloc offset */
|
||||
ldq a0, 8(pv) /* object structure */
|
||||
subq a1, 20, a1 /* = (at - t11 - 20) / 12 * 24 */
|
||||
addq a1, a1, a1
|
||||
|
||||
CALL(_rtld_bind)
|
||||
|
||||
/* Move the destination address into position. */
|
||||
mov $0, $27
|
||||
/* Restore program registers. */
|
||||
ldq $26, 0(sp)
|
||||
ldq $0, 8(sp)
|
||||
ldq $1, 16(sp)
|
||||
ldq $2, 24(sp)
|
||||
ldq $3, 32(sp)
|
||||
ldq $4, 40(sp)
|
||||
ldq $5, 48(sp)
|
||||
ldq $6, 56(sp)
|
||||
ldq $7, 64(sp)
|
||||
ldq $8, 72(sp)
|
||||
ldq $16, 80(sp)
|
||||
ldq $17, 88(sp)
|
||||
ldq $18, 96(sp)
|
||||
ldq $19, 104(sp)
|
||||
ldq $20, 112(sp)
|
||||
ldq $21, 120(sp)
|
||||
ldq $22, 128(sp)
|
||||
ldq $23, 136(sp)
|
||||
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
|
||||
RTLD_BIND_START_EPILOGUE
|
||||
|
||||
END(_rtld_bind_start)
|
||||
|
||||
/*
|
||||
* Lazy binding entry point, called via PLT. This version is for the
|
||||
* old PLT entry format.
|
||||
*/
|
||||
NESTED_NOPROFILE(_rtld_bind_start_old, 0, 168, ra, 0, 0)
|
||||
|
||||
RTLD_BIND_START_PROLOGUE
|
||||
|
||||
/* Set up the arguments for _rtld_bind. */
|
||||
ldq a0, 8(pv) /* object structure */
|
||||
mov at_reg, a1 /* offset of reloc entry */
|
||||
|
||||
CALL(_rtld_bind)
|
||||
|
||||
RTLD_BIND_START_EPILOGUE
|
||||
|
||||
END(_rtld_bind_start_old)
|
||||
|
||||
/*
|
||||
* int cmp0_and_store_int(volatile int *p, int newval);
|
||||
|
Loading…
Reference in New Issue
Block a user