summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2002-02-18 02:24:10 +0000
committerpeter <peter@FreeBSD.org>2002-02-18 02:24:10 +0000
commitcc757467188b1933c356a3895eb1032d3f428a83 (patch)
treee6a2e3b5fdf668ea328e132a7ec844ff3c60d305 /libexec
parentbf46cf3a970cc30c6a24905a3b0fe51de08e976d (diff)
downloadFreeBSD-src-cc757467188b1933c356a3895eb1032d3f428a83.zip
FreeBSD-src-cc757467188b1933c356a3895eb1032d3f428a83.tar.gz
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)
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/alpha/Makefile.inc3
-rw-r--r--libexec/rtld-elf/alpha/ld.so.script135
-rw-r--r--libexec/rtld-elf/alpha/reloc.c18
-rw-r--r--libexec/rtld-elf/alpha/rtld_machdep.h3
-rw-r--r--libexec/rtld-elf/alpha/rtld_start.S178
5 files changed, 265 insertions, 72 deletions
diff --git a/libexec/rtld-elf/alpha/Makefile.inc b/libexec/rtld-elf/alpha/Makefile.inc
index c764115..0f34feb 100644
--- a/libexec/rtld-elf/alpha/Makefile.inc
+++ b/libexec/rtld-elf/alpha/Makefile.inc
@@ -1 +1,4 @@
+# $FreeBSD$
+
CFLAGS+= -mno-fp-regs
+LDFLAGS+= -Wl,--script,${.CURDIR}/alpha/ld.so.script
diff --git a/libexec/rtld-elf/alpha/ld.so.script b/libexec/rtld-elf/alpha/ld.so.script
new file mode 100644
index 0000000..539c0d5
--- /dev/null
+++ b/libexec/rtld-elf/alpha/ld.so.script
@@ -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 . */
+}
diff --git a/libexec/rtld-elf/alpha/reloc.c b/libexec/rtld-elf/alpha/reloc.c
index 7709589..882a8ac 100644
--- a/libexec/rtld-elf/alpha/reloc.c
+++ b/libexec/rtld-elf/alpha/reloc.c
@@ -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;
}
diff --git a/libexec/rtld-elf/alpha/rtld_machdep.h b/libexec/rtld-elf/alpha/rtld_machdep.h
index 11dd60c..777eb0f 100644
--- a/libexec/rtld-elf/alpha/rtld_machdep.h
+++ b/libexec/rtld-elf/alpha/rtld_machdep.h
@@ -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);
diff --git a/libexec/rtld-elf/alpha/rtld_start.S b/libexec/rtld-elf/alpha/rtld_start.S
index 29d6178..d21c088 100644
--- a/libexec/rtld-elf/alpha/rtld_start.S
+++ b/libexec/rtld-elf/alpha/rtld_start.S
@@ -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:
-
- 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
+#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
+
/* 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);
OpenPOWER on IntegriCloud