remove the old elf server, see #2418, should have been part of r10154

git-svn-id: file:///home/svn/framework3/trunk@10155 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
Joshua Drake 2010-08-26 05:24:20 +00:00
parent 6d1ed6d779
commit 067830a8d0
25 changed files with 0 additions and 6218 deletions

View File

@ -1,5 +0,0 @@
CFLAGS+= -elf
LDFLAGS+= -elf
# Uncomment this to build the dynamic linker as an executable instead
# of a shared library:
#LDSCRIPT= ${.CURDIR}/${MACHINE_ARCH}/elf_rtld.x

View File

@ -1,95 +0,0 @@
/* LINTLIBRARY */
/*-
* Copyright 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef lint
#ifndef __GNUC__
#error "GCC is needed to compile this file"
#endif
#endif /* lint */
#include <stdlib.h>
#include "libc_private.h"
#include "crtbrand.c"
extern int _DYNAMIC;
#pragma weak _DYNAMIC
typedef void (*fptr)(void);
extern void _fini(void);
extern void _init(void);
extern int main(int, char **, char **);
extern void _start(char **, void (*)(void));
#ifdef GCRT
extern void _mcleanup(void);
extern void monstartup(void *, void *);
extern int eprol;
extern int etext;
#endif
char **environ;
const char *__progname = "";
/* The entry function. */
void
_start(char **ap, void (*cleanup)(void))
{
int argc;
char **argv;
char **env;
const char *s;
argc = *(long *)(void *)ap;
argv = ap + 1;
env = ap + 2 + argc;
environ = env;
if (argc > 0 && argv[0] != NULL) {
__progname = argv[0];
for (s = __progname; *s != '\0'; s++)
if (*s == '/')
__progname = s + 1;
}
if (&_DYNAMIC != NULL)
atexit(cleanup);
else
_init_tls();
#ifdef GCRT
atexit(_mcleanup);
#endif
atexit(_fini);
#ifdef GCRT
monstartup(&eprol, &etext);
__asm__("eprol:");
#endif
_init();
exit( main(argc, argv, env) );
}
__asm__(".ident\t\"$FreeBSD: head/lib/csu/amd64/crt1.c 151072 2005-10-07 22:13:17Z bde $\"");

View File

@ -1,41 +0,0 @@
/*-
* Copyright 1996, 1997, 1998, 2000 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
.section .init,"ax",@progbits
.align 4
.globl _init
.type _init,@function
_init:
subq $8,%rsp
.section .fini,"ax",@progbits
.align 4
.globl _fini
.type _fini,@function
_fini:
subq $8,%rsp
.section .rodata
.ascii "$FreeBSD: user/kmacy/releng_7_2_zfs/lib/csu/amd64/crti.S 127252 2004-03-21 01:39:01Z peter $\0"

View File

@ -1,35 +0,0 @@
/*-
* Copyright 1996, 1997, 1998, 2000 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
.section .init,"ax",@progbits
addq $8,%rsp
ret
.section .fini,"ax",@progbits
addq $8,%rsp
ret
.section .rodata
.ascii "$FreeBSD: user/kmacy/releng_7_2_zfs/lib/csu/amd64/crtn.S 127252 2004-03-21 01:39:01Z peter $\0"

View File

@ -1,131 +0,0 @@
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
"elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/obj/usr/src/tmp/usr/i386-unknown-freebsdelf/lib);
/* Do we need any of these for elf?
__DYNAMIC = 0; */
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x08000000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.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) } =0x9090
.plt : { *(.plt) }
.text :
{
*(.text)
*(.stub)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
} =0x9090
_etext = .;
PROVIDE (etext = .);
.fini : { *(.fini) } =0x9090
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
/* 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(0x1000) + (. & (0x1000 - 1));
.data :
{
*(.data)
*(.gnu.linkonce.d*)
CONSTRUCTORS
}
.data1 : { *(.data1) }
.ctors :
{
*(.ctors)
}
.dtors :
{
*(.dtors)
}
.got : { *(.got.plt) *(.got) }
.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(32 / 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 . */
}

View File

@ -1,399 +0,0 @@
/*-
* Copyright 1996, 1997, 1998, 1999 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/amd64/reloc.c 157198 2006-03-28 06:09:24Z davidxu $
*/
/*
* Dynamic linker for ELF.
*
* John Polstra <jdp@polstra.com>.
*/
#include <sys/param.h>
#include <sys/mman.h>
#include <machine/sysarch.h>
#include <dlfcn.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "debug.h"
#include "rtld.h"
/*
* Process the special R_X86_64_COPY relocations in the main program. These
* copy data from a shared object into a region in the main program's BSS
* segment.
*
* Returns 0 on success, -1 on failure.
*/
int
do_copy_relocations(Obj_Entry *dstobj)
{
const Elf_Rela *relalim;
const Elf_Rela *rela;
assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + dstobj->relasize);
for (rela = dstobj->rela; rela < relalim; rela++) {
if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) {
void *dstaddr;
const Elf_Sym *dstsym;
const char *name;
unsigned long hash;
size_t size;
const void *srcaddr;
const Elf_Sym *srcsym;
Obj_Entry *srcobj;
const Ver_Entry *ve;
dstaddr = (void *) (dstobj->relocbase + rela->r_offset);
dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
name = dstobj->strtab + dstsym->st_name;
hash = elf_hash(name);
size = dstsym->st_size;
ve = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
if ((srcsym = symlook_obj(name, hash, srcobj, ve, 0)) != NULL)
break;
if (srcobj == NULL) {
_rtld_error("Undefined symbol \"%s\" referenced from COPY"
" relocation in %s", name, dstobj->path);
return -1;
}
srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value);
memcpy(dstaddr, srcaddr, size);
}
}
return 0;
}
/* Initialize the special GOT entries. */
void
init_pltgot(Obj_Entry *obj)
{
if (obj->pltgot != NULL) {
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
}
}
/* Process the non-PLT relocations. */
int
reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
{
const Elf_Rela *relalim;
const Elf_Rela *rela;
SymCache *cache;
int bytes = obj->nchains * sizeof(SymCache);
int r = -1;
/*
* The dynamic loader may be called from a thread, we have
* limited amounts of stack available so we cannot use alloca().
*/
cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
if (cache == MAP_FAILED)
cache = NULL;
relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize);
for (rela = obj->rela; rela < relalim; rela++) {
Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
Elf32_Addr *where32 = (Elf32_Addr *)where;
switch (ELF_R_TYPE(rela->r_info)) {
case R_X86_64_NONE:
break;
case R_X86_64_64:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
if (def == NULL)
goto done;
*where = (Elf_Addr) (defobj->relocbase + def->st_value + rela->r_addend);
}
break;
case R_X86_64_PC32:
/*
* I don't think the dynamic linker should ever see this
* type of relocation. But the binutils-2.6 tools sometimes
* generate it.
*/
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
if (def == NULL)
goto done;
*where32 = (Elf32_Addr) (unsigned long) (defobj->relocbase +
def->st_value + rela->r_addend - (Elf_Addr) where);
}
break;
/* missing: R_X86_64_GOT32 R_X86_64_PLT32 */
case R_X86_64_COPY:
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error("%s: Unexpected R_X86_64_COPY relocation"
" in shared library", obj->path);
goto done;
}
break;
case R_X86_64_GLOB_DAT:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
if (def == NULL)
goto done;
*where = (Elf_Addr) (defobj->relocbase + def->st_value);
}
break;
case R_X86_64_TPOFF64:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
if (def == NULL)
goto done;
/*
* We lazily allocate offsets for static TLS as we
* see the first relocation that references the
* TLS block. This allows us to support (small
* amounts of) static TLS in dynamically loaded
* modules. If we run out of space, we generate an
* error.
*/
if (!defobj->tls_done) {
if (!allocate_tls_offset((Obj_Entry*) defobj)) {
_rtld_error("%s: No space available for static "
"Thread Local Storage", obj->path);
goto done;
}
}
*where = (Elf_Addr) (def->st_value - defobj->tlsoffset +
rela->r_addend);
}
break;
case R_X86_64_TPOFF32:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
if (def == NULL)
goto done;
/*
* We lazily allocate offsets for static TLS as we
* see the first relocation that references the
* TLS block. This allows us to support (small
* amounts of) static TLS in dynamically loaded
* modules. If we run out of space, we generate an
* error.
*/
if (!defobj->tls_done) {
if (!allocate_tls_offset((Obj_Entry*) defobj)) {
_rtld_error("%s: No space available for static "
"Thread Local Storage", obj->path);
goto done;
}
}
*where32 = (Elf32_Addr) (def->st_value -
defobj->tlsoffset +
rela->r_addend);
}
break;
case R_X86_64_DTPMOD64:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
if (def == NULL)
goto done;
*where += (Elf_Addr) defobj->tlsindex;
}
break;
case R_X86_64_DTPOFF64:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
if (def == NULL)
goto done;
*where += (Elf_Addr) (def->st_value + rela->r_addend);
}
break;
case R_X86_64_DTPOFF32:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
false, cache);
if (def == NULL)
goto done;
*where32 += (Elf32_Addr) (def->st_value + rela->r_addend);
}
break;
case R_X86_64_RELATIVE:
*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
break;
/* missing: R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16, R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8 */
default:
_rtld_error("%s: Unsupported relocation type %u"
" in non-PLT relocations\n", obj->path,
(unsigned int)ELF_R_TYPE(rela->r_info));
goto done;
}
}
r = 0;
done:
if (cache)
munmap(cache, bytes);
return(r);
}
/* Process the PLT relocations. */
int
reloc_plt(Obj_Entry *obj)
{
const Elf_Rela *relalim;
const Elf_Rela *rela;
relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
for (rela = obj->pltrela; rela < relalim; rela++) {
Elf_Addr *where;
assert(ELF_R_TYPE(rela->r_info) == R_X86_64_JMP_SLOT);
/* Relocate the GOT slot pointing into the PLT. */
where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
*where += (Elf_Addr)obj->relocbase;
}
return 0;
}
/* Relocate the jump slots in an object. */
int
reloc_jmpslots(Obj_Entry *obj)
{
const Elf_Rela *relalim;
const Elf_Rela *rela;
if (obj->jmpslots_done)
return 0;
relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
for (rela = obj->pltrela; rela < relalim; rela++) {
Elf_Addr *where, target;
const Elf_Sym *def;
const Obj_Entry *defobj;
assert(ELF_R_TYPE(rela->r_info) == R_X86_64_JMP_SLOT);
where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL);
if (def == NULL)
return -1;
target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend);
reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela);
}
obj->jmpslots_done = true;
return 0;
}
void
allocate_initial_tls(Obj_Entry *objs)
{
/*
* Fix the size of the static TLS block by using the maximum
* offset allocated so far and adding a bit for dynamic modules to
* use.
*/
tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA;
amd64_set_fsbase(allocate_tls(objs, 0,
3*sizeof(Elf_Addr), sizeof(Elf_Addr)));
}
void *__tls_get_addr(tls_index *ti)
{
Elf_Addr** segbase;
Elf_Addr* dtv;
__asm __volatile("movq %%fs:0, %0" : "=r" (segbase));
dtv = segbase[1];
return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset);
}

View File

@ -1,80 +0,0 @@
/*-
* Copyright (c) 1999, 2000 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/amd64/rtld_machdep.h 191291 2009-04-19 23:02:50Z rwatson $
*/
#ifndef RTLD_MACHDEP_H
#define RTLD_MACHDEP_H 1
#include <sys/types.h>
#include <machine/atomic.h>
#ifndef CACHE_LINE_SIZE
#define CACHE_LINE_SIZE 128
#endif
struct Struct_Obj_Entry;
/* Return the address of the .dynamic section in the dynamic linker. */
#define rtld_dynamic(obj) \
((const Elf_Dyn *)((obj)->relocbase + (Elf_Addr)&_DYNAMIC))
/* Fixup the jump slot at "where" to transfer control to "target". */
static inline Elf_Addr
reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
const struct Struct_Obj_Entry *obj,
const struct Struct_Obj_Entry *refobj, const Elf_Rel *rel)
{
#ifdef dbg
dbg("reloc_jmpslot: *%p = %p", (void *)(where),
(void *)(target));
#endif
(*(Elf_Addr *)(where) = (Elf_Addr)(target));
return target;
}
#define make_function_pointer(def, defobj) \
((defobj)->relocbase + (def)->st_value)
#define call_initfini_pointer(obj, target) \
(((InitFunc)(target))())
#define round(size, align) \
(((size) + (align) - 1) & ~((align) - 1))
#define calculate_first_tls_offset(size, align) \
round(size, align)
#define calculate_tls_offset(prev_offset, prev_size, size, align) \
round((prev_offset) + (size), align)
#define calculate_tls_end(off, size) (off)
typedef struct {
unsigned long ti_module;
unsigned long ti_offset;
} tls_index;
extern void *__tls_get_addr(tls_index *ti);
#endif

View File

@ -1,114 +0,0 @@
/*-
* Copyright 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/amd64/rtld_start.S 127254 2004-03-21 01:43:39Z peter $
*/
.text
.align 4
.globl .rtld_start
.type .rtld_start,@function
.rtld_start:
xorq %rbp,%rbp # Clear frame pointer for good form
subq $24,%rsp # A place to store exit procedure addr
movq %rdi,%r12
movq %rsp,%rsi # save address of exit proc
movq %rsp,%rdx # construct address of obj_main
addq $8,%rdx
call _rtld_late@PLT # Call rtld(sp); returns entry point
popq %rsi # Get exit procedure address
movq %r12,%rdi # *ap
/*
* At this point, %rax contains the entry point of the main program, and
* %rdx contains a pointer to a termination function that should be
* registered with atexit(). (crt1.o registers it.)
*/
.globl .rtld_goto_main
.rtld_goto_main: # This symbol exists just to make debugging easier.
jmp *%rax # Enter main program
/*
* Binder entry point. Control is transferred to here by code in the PLT.
* On entry, there are two arguments on the stack. In ascending address
* order, they are (1) "obj", a pointer to the calling object's Obj_Entry,
* and (2) "reloff", the byte offset of the appropriate relocation entry
* in the PLT relocation table.
*
* We are careful to preserve all registers, even the the caller-save
* registers. That is because this code may be invoked by low-level
* assembly-language code that is not ABI-compliant.
*
* Stack map:
* reloff 0x60
* obj 0x58
* spare 0x50
* rflags 0x48
* rax 0x40
* rdx 0x38
* rcx 0x30
* rsi 0x28
* rdi 0x20
* r8 0x18
* r9 0x10
* r10 0x8
* r11 0x0
*/
.align 4
.globl _rtld_bind_start
.type _rtld_bind_start,@function
_rtld_bind_start:
subq $8,%rsp
pushfq # Save rflags
pushq %rax # Save %rax
pushq %rdx # Save %rdx
pushq %rcx # Save %rcx
pushq %rsi # Save %rsi
pushq %rdi # Save %rdi
pushq %r8 # Save %r8
pushq %r9 # Save %r9
pushq %r10 # Save %r10
pushq %r11 # Save %r11
movq 0x58(%rsp),%rdi # Fetch obj argument
movq 0x60(%rsp),%rsi # Fetch reloff argument
leaq (%rsi,%rsi,2),%rsi # multiply by 3
leaq (,%rsi,8),%rsi # now 8, for 24 (sizeof Elf_Rela)
call _rtld_bind@PLT # Transfer control to the binder
/* Now %rax contains the entry point of the function being called. */
movq %rax,0x60(%rsp) # Store target over reloff argument
popq %r11 # Restore %r11
popq %r10 # Restore %r10
popq %r9 # Restore %r9
popq %r8 # Restore %r8
popq %rdi # Restore %rdi
popq %rsi # Restore %rsi
popq %rcx # Restore %rcx
popq %rdx # Restore %rdx
popq %rax # Restore %rax
popfq # Restore rflags
leaq 16(%rsp),%rsp # Discard spare, obj, do not change rflags
ret # "Return" to target address

View File

@ -1,52 +0,0 @@
/*-
* Copyright 2000 David E. O'Brien, John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/lib/csu/common/crtbrand.c 174251 2007-12-04 12:18:43Z kib $");
#include <sys/param.h>
#define ABI_VENDOR "FreeBSD"
#define ABI_SECTION ".note.ABI-tag"
#define ABI_NOTETYPE 1
/*
* Special ".note" entry specifying the ABI version. See
* http://www.netbsd.org/Documentation/kernel/elf-notes.html
* for more information.
*/
static const struct {
int32_t namesz;
int32_t descsz;
int32_t type;
char name[sizeof ABI_VENDOR];
int32_t desc;
} abitag __attribute__ ((section (ABI_SECTION), aligned(4))) __used = {
sizeof ABI_VENDOR,
sizeof(int32_t),
ABI_NOTETYPE,
ABI_VENDOR,
__FreeBSD_version
};

View File

@ -1,66 +0,0 @@
/*-
* Copyright 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/debug.h 157219 2006-03-28 18:26:47Z des $
*/
/*
* Support for printing debugging messages.
*/
#ifndef DEBUG_H
#define DEBUG_H 1
#ifndef __GNUC__
#error "This file must be compiled with GCC"
#endif
#include <sys/cdefs.h>
#include <string.h>
#include <unistd.h>
extern void debug_printf(const char *, ...) __printflike(1, 2);
extern int debug;
#ifdef DEBUG
#define dbg(...) debug_printf(__VA_ARGS__)
#else
#define dbg(...) ((void) 0)
#endif
#ifndef COMPAT_32BIT
#define _MYNAME "ld-elf.so.1"
#else
#define _MYNAME "ld-elf32.so.1"
#endif
#define assert(cond) ((cond) ? (void) 0 : \
(msg(_MYNAME ": assert failed: " __FILE__ ":" \
__XSTRING(__LINE__) "\n"), abort()))
#define msg(s) write(STDOUT_FILENO, s, strlen(s))
#define trace() msg(_MYNAME ": " __XSTRING(__LINE__) "\n")
#endif /* DEBUG_H */

View File

@ -1,145 +0,0 @@
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: head/include/dlfcn.h 195745 2009-07-17 19:45:42Z kib $
*/
#ifndef _DLFCN_H_
#define _DLFCN_H_
#include <sys/_types.h>
/*
* Modes and flags for dlopen().
*/
#define RTLD_LAZY 1 /* Bind function calls lazily. */
#define RTLD_NOW 2 /* Bind function calls immediately. */
#define RTLD_MODEMASK 0x3
#define RTLD_GLOBAL 0x100 /* Make symbols globally available. */
#define RTLD_LOCAL 0 /* Opposite of RTLD_GLOBAL, and the default. */
#define RTLD_TRACE 0x200 /* Trace loaded objects and exit. */
#define RTLD_NODELETE 0x01000 /* Do not remove members. */
#define RTLD_NOLOAD 0x02000 /* Do not load if not already loaded. */
/*
* Request arguments for dlinfo().
*/
#define RTLD_DI_LINKMAP 2 /* Obtain link map. */
#define RTLD_DI_SERINFO 4 /* Obtain search path info. */
#define RTLD_DI_SERINFOSIZE 5 /* ... query for required space. */
#define RTLD_DI_ORIGIN 6 /* Obtain object origin */
#define RTLD_DI_MAX RTLD_DI_ORIGIN
/*
* Special handle arguments for dlsym()/dlinfo().
*/
#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */
#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */
#define RTLD_SELF ((void *) -3) /* Search the caller itself. */
#if __BSD_VISIBLE
#ifndef _SIZE_T_DECLARED
typedef __size_t size_t;
#define _SIZE_T_DECLARED
#endif
/*
* Structure filled in by dladdr().
*/
typedef struct dl_info {
const char *dli_fname; /* Pathname of shared object. */
void *dli_fbase; /* Base address of shared object. */
const char *dli_sname; /* Name of nearest symbol. */
void *dli_saddr; /* Address of nearest symbol. */
} Dl_info;
/*-
* The actual type declared by this typedef is immaterial, provided that
* it is a function pointer. Its purpose is to provide a return type for
* dlfunc() which can be cast to a function pointer type without depending
* on behavior undefined by the C standard, which might trigger a compiler
* diagnostic. We intentionally declare a unique type signature to force
* a diagnostic should the application not cast the return value of dlfunc()
* appropriately.
*/
struct __dlfunc_arg {
int __dlfunc_dummy;
};
typedef void (*dlfunc_t)(struct __dlfunc_arg);
/*
* Structures, returned by the RTLD_DI_SERINFO dlinfo() request.
*/
typedef struct dl_serpath {
char * dls_name; /* single search path entry */
unsigned int dls_flags; /* path information */
} Dl_serpath;
typedef struct dl_serinfo {
size_t dls_size; /* total buffer size */
unsigned int dls_cnt; /* number of path entries */
Dl_serpath dls_serpath[1]; /* there may be more than one */
} Dl_serinfo;
#endif /* __BSD_VISIBLE */
__BEGIN_DECLS
/* XSI functions first. */
int dlclose(void *);
const char *
dlerror(void);
void *dlopen(const char *, int);
void *dlopenbuf(const char *, int, unsigned char *, size_t);
void *dlsym(void * __restrict, const char * __restrict);
int dlsocket(void);
#if __BSD_VISIBLE
int dladdr(const void * __restrict, Dl_info * __restrict);
dlfunc_t dlfunc(void * __restrict, const char * __restrict);
int dlinfo(void * __restrict, int, void * __restrict);
void dllockinit(void *_context,
void *(*_lock_create)(void *_context),
void (*_rlock_acquire)(void *_lock),
void (*_wlock_acquire)(void *_lock),
void (*_lock_release)(void *_lock),
void (*_lock_destroy)(void *_lock),
void (*_context_destroy)(void *_context));
void *dlvsym(void * __restrict, const char * __restrict,
const char * __restrict);
#endif /* __BSD_VISIBLE */
__END_DECLS
#endif /* !_DLFCN_H_ */

View File

@ -1,6 +0,0 @@
.globl call_late_start
call_late_start:
add $0x4, %esp
popl %eax
jmp *%eax

View File

@ -1,385 +0,0 @@
/*-
* Copyright 1996, 1997, 1998, 1999 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/i386/reloc.c 157198 2006-03-28 06:09:24Z davidxu $
*/
/*
* Dynamic linker for ELF.
*
* John Polstra <jdp@polstra.com>.
*/
#include <sys/param.h>
#include <sys/mman.h>
#include <machine/segments.h>
#include <machine/sysarch.h>
#include <dlfcn.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "debug.h"
#include "rtld.h"
/*
* Process the special R_386_COPY relocations in the main program. These
* copy data from a shared object into a region in the main program's BSS
* segment.
*
* Returns 0 on success, -1 on failure.
*/
int
do_copy_relocations(Obj_Entry *dstobj)
{
const Elf_Rel *rellim;
const Elf_Rel *rel;
assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize);
for (rel = dstobj->rel; rel < rellim; rel++) {
if (ELF_R_TYPE(rel->r_info) == R_386_COPY) {
void *dstaddr;
const Elf_Sym *dstsym;
const char *name;
unsigned long hash;
size_t size;
const void *srcaddr;
const Elf_Sym *srcsym;
const Ver_Entry *ve;
Obj_Entry *srcobj;
dstaddr = (void *) (dstobj->relocbase + rel->r_offset);
dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
name = dstobj->strtab + dstsym->st_name;
hash = elf_hash(name);
size = dstsym->st_size;
ve = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info));
for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
if ((srcsym = symlook_obj(name, hash, srcobj, ve, 0)) != NULL)
break;
if (srcobj == NULL) {
_rtld_error("Undefined symbol \"%s\" referenced from COPY"
" relocation in %s", name, dstobj->path);
return -1;
}
srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value);
memcpy(dstaddr, srcaddr, size);
}
}
return 0;
}
/* Initialize the special GOT entries. */
void
init_pltgot(Obj_Entry *obj)
{
if (obj->pltgot != NULL) {
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
}
}
/* Process the non-PLT relocations. */
int
reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
{
const Elf_Rel *rellim;
const Elf_Rel *rel;
SymCache *cache;
int bytes = obj->nchains * sizeof(SymCache);
int r = -1;
/*
* The dynamic loader may be called from a thread, we have
* limited amounts of stack available so we cannot use alloca().
*/
cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
if (cache == MAP_FAILED)
cache = NULL;
rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
for (rel = obj->rel; rel < rellim; rel++) {
Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
switch (ELF_R_TYPE(rel->r_info)) {
case R_386_NONE:
break;
case R_386_32:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache);
if (def == NULL) {
printf("lookup failed %d\n", rel->r_info);
goto done;
}
*where += (Elf_Addr) (defobj->relocbase + def->st_value);
}
break;
case R_386_PC32:
/*
* I don't think the dynamic linker should ever see this
* type of relocation. But the binutils-2.6 tools sometimes
* generate it.
*/
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache);
if (def == NULL) {
printf("lookup failed %d\n", rel->r_info);
goto done;
}
if (def == NULL)
goto done;
*where +=
(Elf_Addr) (defobj->relocbase + def->st_value) -
(Elf_Addr) where;
}
break;
case R_386_COPY:
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the COPY
* relocation is not in a shared library. They are allowed
* only in executable files.
*/
if (!obj->mainprog) {
_rtld_error("%s: Unexpected R_386_COPY relocation"
" in shared library", obj->path);
goto done;
}
break;
case R_386_GLOB_DAT:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache);
if (def == NULL) {
printf("lookup failed %d\n", rel->r_info);
goto done;
}
if (def == NULL)
goto done;
*where = (Elf_Addr) (defobj->relocbase + def->st_value);
}
break;
case R_386_RELATIVE:
*where += (Elf_Addr) obj->relocbase;
break;
case R_386_TLS_TPOFF:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache);
if (def == NULL)
goto done;
/*
* We lazily allocate offsets for static TLS as we
* see the first relocation that references the
* TLS block. This allows us to support (small
* amounts of) static TLS in dynamically loaded
* modules. If we run out of space, we generate an
* error.
*/
if (!defobj->tls_done) {
if (!allocate_tls_offset((Obj_Entry*) defobj)) {
_rtld_error("%s: No space available for static "
"Thread Local Storage", obj->path);
goto done;
}
}
*where += (Elf_Addr) (def->st_value - defobj->tlsoffset);
}
break;
case R_386_TLS_DTPMOD32:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache);
if (def == NULL) {
printf("lookup failed %d\n", rel->r_info);
goto done;
}
if (def == NULL)
goto done;
*where += (Elf_Addr) defobj->tlsindex;
}
break;
case R_386_TLS_DTPOFF32:
{
const Elf_Sym *def;
const Obj_Entry *defobj;
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
false, cache);
if (def == NULL) {
printf("lookup failed %d\n", rel->r_info);
goto done;
}
if (def == NULL)
goto done;
*where += (Elf_Addr) def->st_value;
}
break;
default:
_rtld_error("%s: Unsupported relocation type %d"
" in non-PLT relocations\n", obj->path,
ELF_R_TYPE(rel->r_info));
goto done;
}
}
r = 0;
done:
if (cache)
munmap(cache, bytes);
return(r);
}
/* Process the PLT relocations. */
int
reloc_plt(Obj_Entry *obj)
{
const Elf_Rel *rellim;
const Elf_Rel *rel;
rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
for (rel = obj->pltrel; rel < rellim; rel++) {
Elf_Addr *where;
assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT);
/* Relocate the GOT slot pointing into the PLT. */
where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
*where += (Elf_Addr)obj->relocbase;
}
return 0;
}
/* Relocate the jump slots in an object. */
int
reloc_jmpslots(Obj_Entry *obj)
{
const Elf_Rel *rellim;
const Elf_Rel *rel;
if (obj->jmpslots_done)
return 0;
rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
for (rel = obj->pltrel; rel < rellim; rel++) {
Elf_Addr *where, target;
const Elf_Sym *def;
const Obj_Entry *defobj;
assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT);
where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL);
if (def == NULL)
return -1;
target = (Elf_Addr)(defobj->relocbase + def->st_value);
reloc_jmpslot(where, target, defobj, obj, rel);
}
obj->jmpslots_done = true;
return 0;
}
void
allocate_initial_tls(Obj_Entry *objs)
{
void* tls;
/*
* Fix the size of the static TLS block by using the maximum
* offset allocated so far and adding a bit for dynamic modules to
* use.
*/
tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA;
tls = allocate_tls(objs, NULL, 3*sizeof(Elf_Addr), sizeof(Elf_Addr));
#ifndef __linux__
i386_set_gsbase(tls);
#endif
}
/* GNU ABI */
__attribute__((__regparm__(1)))
void *___tls_get_addr(tls_index *ti)
{
Elf_Addr** segbase;
Elf_Addr* dtv;
__asm __volatile("movl %%gs:0, %0" : "=r" (segbase));
dtv = segbase[1];
return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset);
}
/* Sun ABI */
void *__tls_get_addr(tls_index *ti)
{
Elf_Addr** segbase;
Elf_Addr* dtv;
__asm __volatile("movl %%gs:0, %0" : "=r" (segbase));
dtv = segbase[1];
return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset);
}

View File

@ -1,77 +0,0 @@
/*-
* Copyright (c) 1999, 2000 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/i386/rtld_machdep.h 191291 2009-04-19 23:02:50Z rwatson $
*/
#ifndef RTLD_MACHDEP_H
#define RTLD_MACHDEP_H 1
#include <sys/types.h>
#include <machine/atomic.h>
struct Struct_Obj_Entry;
/* Return the address of the .dynamic section in the dynamic linker. */
#define rtld_dynamic(obj) \
((const Elf_Dyn *)((obj)->relocbase + (Elf_Addr)&_DYNAMIC))
/* Fixup the jump slot at "where" to transfer control to "target". */
static __inline Elf_Addr
reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
const struct Struct_Obj_Entry *obj,
const struct Struct_Obj_Entry *refobj, const Elf_Rel *rel)
{
#ifdef dbg
dbg("reloc_jmpslot: *%p = %p", (void *)(where),
(void *)(target));
#endif
(*(Elf_Addr *)(where) = (Elf_Addr)(target));
return target;
}
#define make_function_pointer(def, defobj) \
((defobj)->relocbase + (def)->st_value)
#define call_initfini_pointer(obj, target) \
(((InitFunc)(target))())
#define round(size, align) \
(((size) + (align) - 1) & ~((align) - 1))
#define calculate_first_tls_offset(size, align) \
round(size, align)
#define calculate_tls_offset(prev_offset, prev_size, size, align) \
round((prev_offset) + (size), align)
#define calculate_tls_end(off, size) (off)
typedef struct {
unsigned long ti_module;
unsigned long ti_offset;
} tls_index;
extern void *___tls_get_addr(tls_index *ti) __attribute__((__regparm__(1)));
extern void *__tls_get_addr(tls_index *ti);
#endif

View File

@ -1,92 +0,0 @@
/*-
* Copyright 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/i386/rtld_start.S 146370 2005-05-19 07:32:42Z dfr $
*/
.text
.align 4
.globl .rtld_start
.type .rtld_start,@function
.rtld_start:
xorl %ebp,%ebp # Clear frame pointer for good form
movl %esp,%eax # Save initial stack pointer
movl %esp,%esi # Save initial stack pointer
andl $0xfffffff0,%esp # Align stack pointer
subl $16,%esp # A place to store exit procedure addr
movl %esp,%ebx # save address of exit proc
movl %esp,%ecx # construct address of obj_main
addl $4,%ecx
subl $4,%esp # Keep stack aligned
pushl %ecx # Pass address of obj_main
pushl %ebx # Pass address of exit proc
pushl %eax # Pass initial stack pointer to rtld
call _rtld@PLT # Call rtld(sp); returns entry point
addl $16,%esp # Remove arguments from stack
popl %edx # Get exit procedure address
movl %esi,%esp # Ignore obj_main
/*
* At this point, %eax contains the entry point of the main program, and
* %edx contains a pointer to a termination function that should be
* registered with atexit(). (crt1.o registers it.)
*/
.globl .rtld_goto_main
.rtld_goto_main: # This symbol exists just to make debugging easier.
jmp *%eax # Enter main program
/*
* Binder entry point. Control is transferred to here by code in the PLT.
* On entry, there are two arguments on the stack. In ascending address
* order, they are (1) "obj", a pointer to the calling object's Obj_Entry,
* and (2) "reloff", the byte offset of the appropriate relocation entry
* in the PLT relocation table.
*
* We are careful to preserve all registers, even the the caller-save
* registers. That is because this code may be invoked by low-level
* assembly-language code that is not ABI-compliant.
*/
.align 4
.globl _rtld_bind_start
.type _rtld_bind_start,@function
_rtld_bind_start:
pushf # Save eflags
pushl %eax # Save %eax
pushl %edx # Save %edx
pushl %ecx # Save %ecx
pushl 20(%esp) # Copy reloff argument
pushl 20(%esp) # Copy obj argument
# call _rtld_bind@PLT # Transfer control to the binder
call _rtld_bind # Transfer control to the binder
/* Now %eax contains the entry point of the function being called. */
addl $8,%esp # Discard binder arguments
movl %eax,20(%esp) # Store target over obj argument
popl %ecx # Restore %ecx
popl %edx # Restore %edx
popl %eax # Restore %eax
popf # Restore eflags
leal 4(%esp),%esp # Discard reloff, do not change eflags
ret # "Return" to target address

View File

@ -1,185 +0,0 @@
/*
* Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: head/lib/libc/include/libc_private.h 182225 2008-08-27 02:00:53Z jasone $
*
* Private definitions for libc, libc_r and libpthread.
*
*/
#ifndef _LIBC_PRIVATE_H_
#define _LIBC_PRIVATE_H_
/*
* This global flag is non-zero when a process has created one
* or more threads. It is used to avoid calling locking functions
* when they are not required.
*/
extern int __isthreaded;
/*
* File lock contention is difficult to diagnose without knowing
* where locks were set. Allow a debug library to be built which
* records the source file and line number of each lock call.
*/
#ifdef _FLOCK_DEBUG
#define _FLOCKFILE(x) _flockfile_debug(x, __FILE__, __LINE__)
#else
#define _FLOCKFILE(x) _flockfile(x)
#endif
/*
* Macros for locking and unlocking FILEs. These test if the
* process is threaded to avoid locking when not required.
*/
#define FLOCKFILE(fp) if (__isthreaded) _FLOCKFILE(fp)
#define FUNLOCKFILE(fp) if (__isthreaded) _funlockfile(fp)
/*
* Indexes into the pthread jump table.
*
* Warning! If you change this type, you must also change the threads
* libraries that reference it (libc_r, libpthread).
*/
typedef enum {
PJT_ATFORK,
PJT_ATTR_DESTROY,
PJT_ATTR_GETDETACHSTATE,
PJT_ATTR_GETGUARDSIZE,
PJT_ATTR_GETINHERITSCHED,
PJT_ATTR_GETSCHEDPARAM,
PJT_ATTR_GETSCHEDPOLICY,
PJT_ATTR_GETSCOPE,
PJT_ATTR_GETSTACKADDR,
PJT_ATTR_GETSTACKSIZE,
PJT_ATTR_INIT,
PJT_ATTR_SETDETACHSTATE,
PJT_ATTR_SETGUARDSIZE,
PJT_ATTR_SETINHERITSCHED,
PJT_ATTR_SETSCHEDPARAM,
PJT_ATTR_SETSCHEDPOLICY,
PJT_ATTR_SETSCOPE,
PJT_ATTR_SETSTACKADDR,
PJT_ATTR_SETSTACKSIZE,
PJT_CANCEL,
PJT_CLEANUP_POP,
PJT_CLEANUP_PUSH,
PJT_COND_BROADCAST,
PJT_COND_DESTROY,
PJT_COND_INIT,
PJT_COND_SIGNAL,
PJT_COND_TIMEDWAIT,
PJT_COND_WAIT,
PJT_DETACH,
PJT_EQUAL,
PJT_EXIT,
PJT_GETSPECIFIC,
PJT_JOIN,
PJT_KEY_CREATE,
PJT_KEY_DELETE,
PJT_KILL,
PJT_MAIN_NP,
PJT_MUTEXATTR_DESTROY,
PJT_MUTEXATTR_INIT,
PJT_MUTEXATTR_SETTYPE,
PJT_MUTEX_DESTROY,
PJT_MUTEX_INIT,
PJT_MUTEX_LOCK,
PJT_MUTEX_TRYLOCK,
PJT_MUTEX_UNLOCK,
PJT_ONCE,
PJT_RWLOCK_DESTROY,
PJT_RWLOCK_INIT,
PJT_RWLOCK_RDLOCK,
PJT_RWLOCK_TRYRDLOCK,
PJT_RWLOCK_TRYWRLOCK,
PJT_RWLOCK_UNLOCK,
PJT_RWLOCK_WRLOCK,
PJT_SELF,
PJT_SETCANCELSTATE,
PJT_SETCANCELTYPE,
PJT_SETSPECIFIC,
PJT_SIGMASK,
PJT_TESTCANCEL,
PJT_MAX
} pjt_index_t;
typedef int (*pthread_func_t)(void);
typedef pthread_func_t pthread_func_entry_t[2];
extern pthread_func_entry_t __thr_jtable[];
/*
* yplib internal interfaces
*/
#ifdef YP
int _yp_check(char **);
#endif
/*
* Initialise TLS for static programs
*/
void _init_tls(void);
/*
* Set the TLS thread pointer
*/
void _set_tp(void *tp);
/*
* This is a pointer in the C run-time startup code. It is used
* by getprogname() and setprogname().
*/
extern const char *__progname;
/*
* This function is used by the threading libraries to notify malloc that a
* thread is exiting.
*/
void _malloc_thread_cleanup(void);
/*
* These functions are used by the threading libraries in order to protect
* malloc across fork().
*/
void _malloc_prefork(void);
void _malloc_postfork(void);
/*
* Function to clean up streams, called from abort() and exit().
*/
extern void (*__cleanup)(void);
/*
* Get kern.osreldate to detect ABI revisions. Explicitly
* ignores value of $OSVERSION and caches result. Prototypes
* for the wrapped "new" pad-less syscalls are here for now.
*/
extern int __getosreldate(void);
#endif /* _LIBC_PRIVATE_H_ */

View File

@ -1,10 +0,0 @@
/*
* $FreeBSD: head/libexec/rtld-elf/libmap.h 141232 2005-02-04 02:46:41Z mdodd $
*/
int lm_init (char *);
void lm_fini (void);
char * lm_find (const char *, const char *);
#ifdef COMPAT_32BIT
char * lm_findn (const char *, const char *, const int);
#endif

View File

@ -1,399 +0,0 @@
/*-
* Copyright 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/map_object.c 195743 2009-07-17 19:32:04Z kib $
*/
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "debug.h"
#include "rtld.h"
static Elf_Ehdr *get_elf_header(const char *path, char *buf, ssize_t nbytes);
static int convert_prot(int); /* Elf flags -> mmap protection */
static int convert_flags(int); /* Elf flags -> mmap flags */
/*
* Map a shared object into memory. The "fd" argument is a file descriptor,
* which must be open on the object and positioned at its beginning.
* The "path" argument is a pathname that is used only for error messages.
*
* The return value is a pointer to a newly-allocated Obj_Entry structure
* for the shared object. Returns NULL on failure.
*/
Obj_Entry *
map_object(const char *path, char *buf, ssize_t size)
{
Obj_Entry *obj;
Elf_Ehdr *hdr;
int i;
Elf_Phdr *phdr;
Elf_Phdr *phlimit;
Elf_Phdr **segs;
int nsegs;
Elf_Phdr *phdyn;
Elf_Phdr *phinterp;
Elf_Phdr *phtls;
caddr_t mapbase;
size_t mapsize;
Elf_Off base_offset;
Elf_Addr base_vaddr;
Elf_Addr base_vlimit;
caddr_t base_addr;
Elf_Off data_offset;
Elf_Addr data_vaddr;
Elf_Addr data_vlimit;
caddr_t data_addr;
int data_prot;
int data_flags;
Elf_Addr clear_vaddr;
caddr_t clear_addr;
caddr_t clear_page;
Elf_Addr phdr_vaddr;
size_t nclear, phsize;
Elf_Addr bss_vaddr;
Elf_Addr bss_vlimit;
caddr_t bss_addr;
hdr = get_elf_header(path, buf, size);
if (hdr == NULL)
return (NULL);
/*
* Scan the program header entries, and save key information.
*
* We expect that the loadable segments are ordered by load address.
*/
phdr = (Elf_Phdr *) ((char *)hdr + hdr->e_phoff);
phsize = hdr->e_phnum * sizeof (phdr[0]);
phlimit = phdr + hdr->e_phnum;
nsegs = -1;
phdyn = phinterp = phtls = NULL;
phdr_vaddr = 0;
segs = alloca(sizeof(segs[0]) * hdr->e_phnum);
while (phdr < phlimit) {
switch (phdr->p_type) {
case PT_INTERP:
phinterp = phdr;
break;
case PT_LOAD:
segs[++nsegs] = phdr;
if ((segs[nsegs]->p_align & (PAGE_SIZE - 1)) != 0) {
_rtld_error("%s: PT_LOAD segment %d not page-aligned",
path, nsegs);
return NULL;
}
break;
case PT_PHDR:
phdr_vaddr = phdr->p_vaddr;
phsize = phdr->p_memsz;
break;
case PT_DYNAMIC:
phdyn = phdr;
break;
case PT_TLS:
phtls = phdr;
break;
}
++phdr;
}
if (phdyn == NULL) {
_rtld_error("%s: object is not dynamically-linked", path);
return NULL;
}
if (nsegs < 0) {
_rtld_error("%s: too few PT_LOAD segments", path);
return NULL;
}
/*
* Map the entire address space of the object, to stake out our
* contiguous region, and to establish the base address for relocation.
*/
base_offset = trunc_page(segs[0]->p_offset);
base_vaddr = trunc_page(segs[0]->p_vaddr);
base_vlimit = round_page(segs[nsegs]->p_vaddr + segs[nsegs]->p_memsz);
mapsize = base_vlimit - base_vaddr;
base_addr = hdr->e_type == ET_EXEC ? (caddr_t) base_vaddr : NULL;
mapbase = mmap(base_addr, mapsize, PROT_NONE, MAP_ANON | MAP_PRIVATE |
MAP_NOCORE, -1, 0);
if (mapbase == (caddr_t) -1) {
_rtld_error("%s: mmap of entire address space failed: %s",
path, strerror(errno));
return NULL;
}
if (base_addr != NULL && mapbase != base_addr) {
_rtld_error("%s: mmap returned wrong address: wanted %p, got %p",
path, base_addr, mapbase);
munmap(mapbase, mapsize);
return NULL;
}
for (i = 0; i <= nsegs; i++) {
size_t data_vsize;
/* Overlay the segment onto the proper region. */
data_offset = trunc_page(segs[i]->p_offset);
data_vaddr = trunc_page(segs[i]->p_vaddr);
data_vlimit = round_page(segs[i]->p_vaddr + segs[i]->p_filesz);
data_addr = mapbase + (data_vaddr - base_vaddr);
data_prot = convert_prot(segs[i]->p_flags) | PROT_WRITE;
data_vsize = data_vlimit - data_vaddr;
data_flags = convert_flags(segs[i]->p_flags) | \
MAP_FIXED | MAP_ANON | MAP_PRIVATE;
if (mmap(data_addr, data_vsize, data_prot, data_flags,
-1, data_offset) == (caddr_t) -1) {
_rtld_error("%s: mmap of data failed: %s", path, strerror(errno));
return NULL;
}
bcopy(buf + data_offset, data_addr, MIN(data_vsize, (size - data_offset)));
/* Do BSS setup */
if (segs[i]->p_filesz != segs[i]->p_memsz) {
/* Clear any BSS in the last page of the segment. */
clear_vaddr = segs[i]->p_vaddr + segs[i]->p_filesz;
clear_addr = mapbase + (clear_vaddr - base_vaddr);
clear_page = mapbase + (trunc_page(clear_vaddr) - base_vaddr);
if ((nclear = data_vlimit - clear_vaddr) > 0) {
/* Make sure the end of the segment is writable */
if ((data_prot & PROT_WRITE) == 0 && -1 ==
mprotect(clear_page, PAGE_SIZE, data_prot|PROT_WRITE)) {
_rtld_error("%s: mprotect failed: %s", path,
strerror(errno));
return NULL;
}
memset(clear_addr, 0, nclear);
/* Reset the data protection back */
if ((data_prot & PROT_WRITE) == 0)
mprotect(clear_page, PAGE_SIZE, data_prot);
}
/* Overlay the BSS segment onto the proper region. */
bss_vaddr = data_vlimit;
bss_vlimit = round_page(segs[i]->p_vaddr + segs[i]->p_memsz);
bss_addr = mapbase + (bss_vaddr - base_vaddr);
if (bss_vlimit > bss_vaddr) { /* There is something to do */
if (mprotect(bss_addr, bss_vlimit - bss_vaddr, data_prot) == -1) {
_rtld_error("%s: mprotect of bss failed: %s", path,
strerror(errno));
return NULL;
}
}
}
if (phdr_vaddr == 0 && data_offset <= hdr->e_phoff &&
(data_vlimit - data_vaddr + data_offset) >=
(hdr->e_phoff + hdr->e_phnum * sizeof (Elf_Phdr))) {
phdr_vaddr = data_vaddr + hdr->e_phoff - data_offset;
}
}
obj = obj_new();
obj->mapbase = mapbase;
obj->mapsize = mapsize;
obj->textsize = round_page(segs[0]->p_vaddr + segs[0]->p_memsz) -
base_vaddr;
obj->vaddrbase = base_vaddr;
obj->relocbase = mapbase - base_vaddr;
obj->dynamic = (const Elf_Dyn *) (obj->relocbase + phdyn->p_vaddr);
if (hdr->e_entry != 0)
obj->entry = (caddr_t) (obj->relocbase + hdr->e_entry);
if (phdr_vaddr != 0) {
obj->phdr = (const Elf_Phdr *) (obj->relocbase + phdr_vaddr);
} else {
obj->phdr = malloc(phsize);
if (obj->phdr == NULL) {
obj_free(obj);
_rtld_error("%s: cannot allocate program header", path);
return NULL;
}
memcpy((char *)obj->phdr, (char *)hdr + hdr->e_phoff, phsize);
obj->phdr_alloc = true;
}
obj->phsize = phsize;
if (phinterp != NULL)
obj->interp = (const char *) (obj->relocbase + phinterp->p_vaddr);
if (phtls != NULL) {
tls_dtv_generation++;
obj->tlsindex = ++tls_max_index;
obj->tlssize = phtls->p_memsz;
obj->tlsalign = phtls->p_align;
obj->tlsinitsize = phtls->p_filesz;
obj->tlsinit = mapbase + phtls->p_vaddr;
}
return obj;
}
static Elf_Ehdr *
get_elf_header (const char *path, char *buf, ssize_t nbytes)
{
Elf_Ehdr hdr = *(Elf_Ehdr *)buf;
/* Make sure the file is valid */
if (nbytes < (ssize_t)sizeof(Elf_Ehdr) || !IS_ELF(hdr)) {
_rtld_error("%s: invalid file format", path);
return NULL;
}
if (hdr.e_ident[EI_CLASS] != ELF_TARG_CLASS
|| hdr.e_ident[EI_DATA] != ELF_TARG_DATA) {
_rtld_error("%s: unsupported file layout", path);
return NULL;
}
if (hdr.e_ident[EI_VERSION] != EV_CURRENT
|| hdr.e_version != EV_CURRENT) {
_rtld_error("%s: unsupported file version", path);
return NULL;
}
if (hdr.e_type != ET_EXEC && hdr.e_type != ET_DYN) {
_rtld_error("%s: unsupported file type", path);
return NULL;
}
if (hdr.e_machine != ELF_TARG_MACH) {
_rtld_error("%s: unsupported machine", path);
return NULL;
}
/*
* We rely on the program header being in the first page. This is
* not strictly required by the ABI specification, but it seems to
* always true in practice. And, it simplifies things considerably.
*/
if (hdr.e_phentsize != sizeof(Elf_Phdr)) {
_rtld_error(
"%s: invalid shared object: e_phentsize != sizeof(Elf_Phdr)", path);
return NULL;
}
if (hdr.e_phoff + hdr.e_phnum * sizeof(Elf_Phdr) > (size_t)nbytes) {
_rtld_error("%s: program header too large", path);
return NULL;
}
return (Elf_Ehdr *)buf;
}
void
obj_free(Obj_Entry *obj)
{
Objlist_Entry *elm;
if (obj->tls_done)
free_tls_offset(obj);
while (obj->needed != NULL) {
Needed_Entry *needed = obj->needed;
obj->needed = needed->next;
free(needed);
}
while (!STAILQ_EMPTY(&obj->names)) {
Name_Entry *entry = STAILQ_FIRST(&obj->names);
STAILQ_REMOVE_HEAD(&obj->names, link);
free(entry);
}
while (!STAILQ_EMPTY(&obj->dldags)) {
elm = STAILQ_FIRST(&obj->dldags);
STAILQ_REMOVE_HEAD(&obj->dldags, link);
free(elm);
}
while (!STAILQ_EMPTY(&obj->dagmembers)) {
elm = STAILQ_FIRST(&obj->dagmembers);
STAILQ_REMOVE_HEAD(&obj->dagmembers, link);
free(elm);
}
if (obj->vertab)
free(obj->vertab);
if (obj->origin_path)
free(obj->origin_path);
if (obj->z_origin)
free(obj->rpath);
if (obj->priv)
free(obj->priv);
if (obj->path)
free(obj->path);
if (obj->phdr_alloc)
free((void *)obj->phdr);
free(obj);
}
Obj_Entry *
obj_new(void)
{
Obj_Entry *obj;
obj = CNEW(Obj_Entry);
STAILQ_INIT(&obj->dldags);
STAILQ_INIT(&obj->dagmembers);
STAILQ_INIT(&obj->names);
return obj;
}
/*
* Given a set of ELF protection flags, return the corresponding protection
* flags for MMAP.
*/
static int
convert_prot(int elfflags)
{
int prot = 0;
if (elfflags & PF_R)
prot |= PROT_READ;
if (elfflags & PF_W)
prot |= PROT_WRITE;
if (elfflags & PF_X)
prot |= PROT_EXEC;
return prot;
}
static int
convert_flags(int elfflags)
{
int flags = MAP_PRIVATE; /* All mappings are private */
/*
* Readonly mappings are marked "MAP_NOCORE", because they can be
* reconstructed by a debugger.
*/
if (!(elfflags & PF_W))
flags |= MAP_NOCORE;
return flags;
}

View File

@ -1,314 +0,0 @@
/*-
* Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/rtld.h 194531 2009-06-20 14:16:41Z kan $
*/
#ifndef RTLD_H /* { */
#define RTLD_H 1
#define IN_LIBLOADER
#include <sys/link_elf.h>
#include <sys/queue.h>
#include "rtld_lock.h"
#include "rtld_machdep.h"
#ifdef COMPAT_32BIT
#undef STANDARD_LIBRARY_PATH
#undef _PATH_ELF_HINTS
#define _PATH_ELF_HINTS "/var/run/ld-elf32.so.hints"
/* For running 32 bit binaries */
#define STANDARD_LIBRARY_PATH "/lib32:/usr/lib32"
#define LD_ "LD_32_"
#endif
#ifndef STANDARD_LIBRARY_PATH
#define STANDARD_LIBRARY_PATH "/lib:/usr/lib"
#endif
#ifndef LD_
#define LD_ "LD_"
#endif
#define NEW(type) ((type *) xmalloc(sizeof(type)))
#define CNEW(type) ((type *) xcalloc(sizeof(type)))
/* We might as well do booleans like C++. */
typedef unsigned char bool;
#define false 0
#define true 1
extern size_t tls_last_offset;
extern size_t tls_last_size;
extern size_t tls_static_space;
extern int tls_dtv_generation;
extern int tls_max_index;
extern int __loader_socket;
struct stat;
struct Struct_Obj_Entry;
/* Lists of shared objects */
typedef struct Struct_Objlist_Entry {
STAILQ_ENTRY(Struct_Objlist_Entry) link;
struct Struct_Obj_Entry *obj;
} Objlist_Entry;
typedef STAILQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist;
/* Types of init and fini functions */
typedef void (*InitFunc)(void);
/* Lists of shared object dependencies */
typedef struct Struct_Needed_Entry {
struct Struct_Needed_Entry *next;
struct Struct_Obj_Entry *obj;
unsigned long name; /* Offset of name in string table */
} Needed_Entry;
typedef struct Struct_Name_Entry {
STAILQ_ENTRY(Struct_Name_Entry) link;
char name[1];
} Name_Entry;
/* Lock object */
typedef struct Struct_LockInfo {
void *context; /* Client context for creating locks */
void *thelock; /* The one big lock */
/* Debugging aids. */
volatile int rcount; /* Number of readers holding lock */
volatile int wcount; /* Number of writers holding lock */
/* Methods */
void *(*lock_create)(void *context);
void (*rlock_acquire)(void *lock);
void (*wlock_acquire)(void *lock);
void (*rlock_release)(void *lock);
void (*wlock_release)(void *lock);
void (*lock_destroy)(void *lock);
void (*context_destroy)(void *context);
} LockInfo;
typedef struct Struct_Ver_Entry {
Elf_Word hash;
unsigned int flags;
const char *name;
const char *file;
} Ver_Entry;
#define VER_INFO_HIDDEN 0x01
/*
* Shared object descriptor.
*
* Items marked with "(%)" are dynamically allocated, and must be freed
* when the structure is destroyed.
*
* CAUTION: It appears that the JDK port peeks into these structures.
* It looks at "next" and "mapbase" at least. Don't add new members
* near the front, until this can be straightened out.
*/
typedef struct Struct_Obj_Entry {
/*
* These two items have to be set right for compatibility with the
* original ElfKit crt1.o.
*/
Elf_Size magic; /* Magic number (sanity check) */
Elf_Size version; /* Version number of struct format */
struct Struct_Obj_Entry *next;
char *path; /* Pathname of underlying file (%) */
char *origin_path; /* Directory path of origin file */
int refcount;
int dl_refcount; /* Number of times loaded by dlopen */
/* These items are computed by map_object() or by digest_phdr(). */
caddr_t mapbase; /* Base address of mapped region */
size_t mapsize; /* Size of mapped region in bytes */
size_t textsize; /* Size of text segment in bytes */
Elf_Addr vaddrbase; /* Base address in shared object file */
caddr_t relocbase; /* Relocation constant = mapbase - vaddrbase */
const Elf_Dyn *dynamic; /* Dynamic section */
caddr_t entry; /* Entry point */
const Elf_Phdr *phdr; /* Program header if it is mapped, else NULL */
size_t phsize; /* Size of program header in bytes */
const char *interp; /* Pathname of the interpreter, if any */
/* TLS information */
int tlsindex; /* Index in DTV for this module */
void *tlsinit; /* Base address of TLS init block */
size_t tlsinitsize; /* Size of TLS init block for this module */
size_t tlssize; /* Size of TLS block for this module */
size_t tlsoffset; /* Offset of static TLS block for this module */
size_t tlsalign; /* Alignment of static TLS block */
/* Items from the dynamic section. */
Elf_Addr *pltgot; /* PLT or GOT, depending on architecture */
const Elf_Rel *rel; /* Relocation entries */
unsigned long relsize; /* Size in bytes of relocation info */
const Elf_Rela *rela; /* Relocation entries with addend */
unsigned long relasize; /* Size in bytes of addend relocation info */
const Elf_Rel *pltrel; /* PLT relocation entries */
unsigned long pltrelsize; /* Size in bytes of PLT relocation info */
const Elf_Rela *pltrela; /* PLT relocation entries with addend */
unsigned long pltrelasize; /* Size in bytes of PLT addend reloc info */
const Elf_Sym *symtab; /* Symbol table */
const char *strtab; /* String table */
unsigned long strsize; /* Size in bytes of string table */
#ifdef __mips__
Elf_Word local_gotno; /* Number of local GOT entries */
Elf_Word symtabno; /* Number of dynamic symbols */
Elf_Word gotsym; /* First dynamic symbol in GOT */
#endif
const Elf_Verneed *verneed; /* Required versions. */
Elf_Word verneednum; /* Number of entries in verneed table */
const Elf_Verdef *verdef; /* Provided versions. */
Elf_Word verdefnum; /* Number of entries in verdef table */
const Elf_Versym *versyms; /* Symbol versions table */
union
{
const Elf32_Word *gnu_buckets;
const Elf_Hashelt *chains;/* Hash table chain array */
};
union
{
const Elf32_Word *gnu_chain_zero;
const Elf_Hashelt *buckets; /* Hash table buckets array */
};
unsigned long nbuckets; /* Number of buckets */
unsigned long nchains; /* Number of chains */
Elf32_Word gnu_bitmask_idxbits;
Elf32_Word gnu_shift;
const Elf_Addr *gnu_bitmask;
char *rpath; /* Search path specified in object */
Needed_Entry *needed; /* Shared objects needed by this one (%) */
STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we
know about. */
Ver_Entry *vertab; /* Versions required /defined by this object */
int vernum; /* Number of entries in vertab */
Elf_Addr init; /* Initialization function to call */
Elf_Addr fini; /* Termination function to call */
bool mainprog : 1; /* True if this is the main program */
bool rtld : 1; /* True if this is the dynamic linker */
bool textrel : 1; /* True if there are relocations to text seg */
bool symbolic : 1; /* True if generated with "-Bsymbolic" */
bool bind_now : 1; /* True if all relocations should be made first */
bool traced : 1; /* Already printed in ldd trace output */
bool jmpslots_done : 1; /* Already have relocated the jump slots */
bool init_done : 1; /* Already have added object to init list */
bool tls_done : 1; /* Already allocated offset for static TLS */
bool phdr_alloc : 1; /* Phdr is allocated and needs to be freed. */
bool z_origin : 1; /* Process rpath and soname tokens */
bool z_nodelete : 1; /* Do not unload the object and dependencies */
bool ref_nodel : 1; /* Refcount increased to prevent dlclose */
bool init_scanned: 1; /* Object is already on init list. */
bool on_fini_list: 1; /* Object is already on fini list. */
struct link_map linkmap; /* For GDB and dlinfo() */
Objlist dldags; /* Object belongs to these dlopened DAGs (%) */
Objlist dagmembers; /* DAG has these members (%) */
dev_t dev; /* Object's filesystem's device */
ino_t ino; /* Object's inode number */
void *priv; /* Platform-dependant */
} Obj_Entry;
#define RTLD_MAGIC 0xd550b87a
#define RTLD_VERSION 1
#define RTLD_STATIC_TLS_EXTRA 128
/* Flags to be passed into symlook_ family of functions. */
#define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */
#define SYMLOOK_DLSYM 0x02 /* Return newes versioned symbol. Used by
dlsym. */
/*
* Symbol cache entry used during relocation to avoid multiple lookups
* of the same symbol.
*/
typedef struct Struct_SymCache {
const Elf_Sym *sym; /* Symbol table entry */
const Obj_Entry *obj; /* Shared object which defines it */
} SymCache;
extern void _rtld_error(const char *, ...) __printflike(1, 2);
extern Obj_Entry *map_object(const char *, char *, ssize_t);
extern void *xcalloc(size_t);
extern void *xmalloc(size_t);
extern char *xstrdup(const char *);
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
extern void dump_relocations (Obj_Entry *);
extern void dump_obj_relocations (Obj_Entry *);
extern void dump_Elf_Rel (Obj_Entry *, const Elf_Rel *, u_long);
extern void dump_Elf_Rela (Obj_Entry *, const Elf_Rela *, u_long);
/*
* Function declarations.
*/
unsigned long elf_hash(const char *);
const Elf_Sym *find_symdef(unsigned long, const Obj_Entry *,
const Obj_Entry **, int, SymCache *);
void init_pltgot(Obj_Entry *);
void lockdflt_init(void);
void obj_free(Obj_Entry *);
Obj_Entry *obj_new(void);
void _rtld_bind_start(void);
const Elf_Sym *symlook_obj(const char *, unsigned long, const Obj_Entry *,
const Ver_Entry *, int);
void *tls_get_addr_common(Elf_Addr** dtvp, int index, size_t offset);
void *allocate_tls(Obj_Entry *, void *, size_t, size_t);
void free_tls(void *, size_t, size_t);
void *allocate_module_tls(int index);
bool allocate_tls_offset(Obj_Entry *obj);
void free_tls_offset(Obj_Entry *obj);
const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long);
int open_object(const char *name, unsigned char **, ssize_t *, void *buf);
/*
* MD function declarations.
*/
int do_copy_relocations(Obj_Entry *);
int reloc_non_plt(Obj_Entry *, Obj_Entry *);
int reloc_plt(Obj_Entry *);
int reloc_jmpslots(Obj_Entry *);
void allocate_initial_tls(Obj_Entry *);
void *rtld_malloc(size_t);
void rtld_free(void *);
#define malloc rtld_malloc
#define free rtld_free
#endif /* } */

File diff suppressed because it is too large Load Diff

View File

@ -1,336 +0,0 @@
/*-
* Copyright 1999, 2000 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* from: FreeBSD: src/libexec/rtld-elf/sparc64/lockdflt.c,v 1.3 2002/10/09
* $FreeBSD: head/libexec/rtld-elf/rtld_lock.c 191303 2009-04-20 10:35:50Z rwatson $
*/
/*
* Thread locking implementation for the dynamic linker.
*
* We use the "simple, non-scalable reader-preference lock" from:
*
* J. M. Mellor-Crummey and M. L. Scott. "Scalable Reader-Writer
* Synchronization for Shared-Memory Multiprocessors." 3rd ACM Symp. on
* Principles and Practice of Parallel Programming, April 1991.
*
* In this algorithm the lock is a single word. Its low-order bit is
* set when a writer holds the lock. The remaining high-order bits
* contain a count of readers desiring the lock. The algorithm requires
* atomic "compare_and_store" and "add" operations, which we implement
* using assembly language sequences in "rtld_start.S".
*/
#include <sys/param.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
#include "debug.h"
#include "rtld.h"
#include "rtld_machdep.h"
#define WAFLAG 0x1 /* A writer holds the lock */
#define RC_INCR 0x2 /* Adjusts count of readers desiring lock */
typedef struct Struct_Lock {
volatile u_int lock;
void *base;
} Lock;
static sigset_t fullsigmask, oldsigmask;
static int thread_flag;
static void *
def_lock_create()
{
void *base;
char *p;
uintptr_t r;
Lock *l;
/*
* Arrange for the lock to occupy its own cache line. First, we
* optimistically allocate just a cache line, hoping that malloc
* will give us a well-aligned block of memory. If that doesn't
* work, we allocate a larger block and take a well-aligned cache
* line from it.
*/
base = xmalloc(CACHE_LINE_SIZE);
p = (char *)base;
if ((uintptr_t)p % CACHE_LINE_SIZE != 0) {
free(base);
base = xmalloc(2 * CACHE_LINE_SIZE);
p = (char *)base;
if ((r = (uintptr_t)p % CACHE_LINE_SIZE) != 0)
p += CACHE_LINE_SIZE - r;
}
l = (Lock *)p;
l->base = base;
l->lock = 0;
return l;
}
static void
def_lock_destroy(void *lock)
{
Lock *l = (Lock *)lock;
free(l->base);
}
static void
def_rlock_acquire(void *lock)
{
Lock *l = (Lock *)lock;
atomic_add_acq_int(&l->lock, RC_INCR);
while (l->lock & WAFLAG)
; /* Spin */
}
static void
def_wlock_acquire(void *lock)
{
Lock *l = (Lock *)lock;
sigset_t tmp_oldsigmask;
for ( ; ; ) {
sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask);
if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG))
break;
sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL);
}
oldsigmask = tmp_oldsigmask;
}
static void
def_lock_release(void *lock)
{
Lock *l = (Lock *)lock;
if ((l->lock & WAFLAG) == 0)
atomic_add_rel_int(&l->lock, -RC_INCR);
else {
atomic_add_rel_int(&l->lock, -WAFLAG);
sigprocmask(SIG_SETMASK, &oldsigmask, NULL);
}
}
static int
def_thread_set_flag(int mask)
{
int old_val = thread_flag;
thread_flag |= mask;
return (old_val);
}
static int
def_thread_clr_flag(int mask)
{
int old_val = thread_flag;
thread_flag &= ~mask;
return (old_val);
}
/*
* Public interface exposed to the rest of the dynamic linker.
*/
static struct RtldLockInfo lockinfo;
static struct RtldLockInfo deflockinfo;
static __inline int
thread_mask_set(int mask)
{
return lockinfo.thread_set_flag(mask);
}
static __inline void
thread_mask_clear(int mask)
{
lockinfo.thread_clr_flag(mask);
}
#define RTLD_LOCK_CNT 3
struct rtld_lock {
void *handle;
int mask;
} late_rtld_locks[RTLD_LOCK_CNT];
rtld_lock_t late_rtld_bind_lock = &late_rtld_locks[0];
rtld_lock_t late_rtld_libc_lock = &late_rtld_locks[1];
rtld_lock_t late_rtld_phdr_lock = &late_rtld_locks[2];
int
rlock_acquire(rtld_lock_t lock)
{
if (thread_mask_set(lock->mask) & lock->mask) {
dbg("rlock_acquire: recursed");
return (0);
}
lockinfo.rlock_acquire(lock->handle);
return (1);
}
int
wlock_acquire(rtld_lock_t lock)
{
if (thread_mask_set(lock->mask) & lock->mask) {
dbg("wlock_acquire: recursed");
return (0);
}
lockinfo.wlock_acquire(lock->handle);
return (1);
}
void
rlock_release(rtld_lock_t lock, int locked)
{
if (locked == 0)
return;
thread_mask_clear(lock->mask);
lockinfo.lock_release(lock->handle);
}
void
wlock_release(rtld_lock_t lock, int locked)
{
if (locked == 0)
return;
thread_mask_clear(lock->mask);
lockinfo.lock_release(lock->handle);
}
void
late_lockdflt_init()
{
int i;
deflockinfo.rtli_version = RTLI_VERSION;
deflockinfo.lock_create = def_lock_create;
deflockinfo.lock_destroy = def_lock_destroy;
deflockinfo.rlock_acquire = def_rlock_acquire;
deflockinfo.wlock_acquire = def_wlock_acquire;
deflockinfo.lock_release = def_lock_release;
deflockinfo.thread_set_flag = def_thread_set_flag;
deflockinfo.thread_clr_flag = def_thread_clr_flag;
deflockinfo.at_fork = NULL;
for (i = 0; i < RTLD_LOCK_CNT; i++) {
late_rtld_locks[i].mask = (1 << i);
late_rtld_locks[i].handle = NULL;
}
memcpy(&lockinfo, &deflockinfo, sizeof(lockinfo));
_late_rtld_thread_init(NULL);
/*
* Construct a mask to block all signals except traps which might
* conceivably be generated within the dynamic linker itself.
*/
_sigfillset(&fullsigmask);
_sigdelset(&fullsigmask, SIGILL);
_sigdelset(&fullsigmask, SIGTRAP);
_sigdelset(&fullsigmask, SIGABRT);
_sigdelset(&fullsigmask, SIGEMT);
_sigdelset(&fullsigmask, SIGFPE);
_sigdelset(&fullsigmask, SIGBUS);
_sigdelset(&fullsigmask, SIGSEGV);
_sigdelset(&fullsigmask, SIGSYS);
}
/*
* Callback function to allow threads implementation to
* register their own locking primitives if the default
* one is not suitable.
* The current context should be the only context
* executing at the invocation time.
*/
void
_late_rtld_thread_init(struct RtldLockInfo *pli)
{
int flags, i;
void *locks[RTLD_LOCK_CNT];
/* disable all locking while this function is running */
flags = thread_mask_set(~0);
if (pli == NULL)
pli = &deflockinfo;
for (i = 0; i < RTLD_LOCK_CNT; i++)
if ((locks[i] = pli->lock_create()) == NULL)
break;
if (i < RTLD_LOCK_CNT) {
while (--i >= 0)
pli->lock_destroy(locks[i]);
abort();
}
for (i = 0; i < RTLD_LOCK_CNT; i++) {
if (late_rtld_locks[i].handle == NULL)
continue;
if (flags & late_rtld_locks[i].mask)
lockinfo.lock_release(late_rtld_locks[i].handle);
lockinfo.lock_destroy(late_rtld_locks[i].handle);
}
for (i = 0; i < RTLD_LOCK_CNT; i++) {
late_rtld_locks[i].handle = locks[i];
if (flags & late_rtld_locks[i].mask)
pli->wlock_acquire(late_rtld_locks[i].handle);
}
lockinfo.lock_create = pli->lock_create;
lockinfo.lock_destroy = pli->lock_destroy;
lockinfo.rlock_acquire = pli->rlock_acquire;
lockinfo.wlock_acquire = pli->wlock_acquire;
lockinfo.lock_release = pli->lock_release;
lockinfo.thread_set_flag = pli->thread_set_flag;
lockinfo.thread_clr_flag = pli->thread_clr_flag;
lockinfo.at_fork = pli->at_fork;
/* restore thread locking state, this time with new locks */
thread_mask_clear(~0);
thread_mask_set(flags);
dbg("_rtld_thread_init: done");
}
void
_late_rtld_atfork_pre(int *locks)
{
locks[2] = wlock_acquire(late_rtld_phdr_lock);
locks[0] = rlock_acquire(late_rtld_bind_lock);
}
void
_late_rtld_atfork_post(int *locks)
{
rlock_release(late_rtld_bind_lock, locks[0]);
wlock_release(late_rtld_phdr_lock, locks[2]);
}

View File

@ -1,67 +0,0 @@
/*-
* Copyright 2003 Alexander Kabaev.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/rtld_lock.h 185558 2008-12-02 11:58:31Z kib $
*/
#ifndef _RTLD_LOCK_H_
#define _RTLD_LOCK_H_
#define RTLI_VERSION 0x01
#define MAX_RTLD_LOCKS 8
struct RtldLockInfo
{
unsigned int rtli_version;
void *(*lock_create)(void);
void (*lock_destroy)(void *);
void (*rlock_acquire)(void *);
void (*wlock_acquire)(void *);
void (*lock_release)(void *);
int (*thread_set_flag)(int);
int (*thread_clr_flag)(int);
void (*at_fork)(void);
};
extern void _late_rtld_thread_init(struct RtldLockInfo *);
extern void _rtld_atfork_pre(int *);
extern void _rtld_atfork_post(int *);
#ifdef IN_RTLD
struct rtld_lock;
typedef struct rtld_lock *rtld_lock_t;
extern rtld_lock_t late_rtld_bind_lock;
extern rtld_lock_t late_rtld_libc_lock;
extern rtld_lock_t late_rtld_phdr_lock;
int rlock_acquire(rtld_lock_t);
int wlock_acquire(rtld_lock_t);
void rlock_release(rtld_lock_t, int);
void wlock_release(rtld_lock_t, int);
#endif /* IN_RTLD */
#endif

View File

@ -1,515 +0,0 @@
/*-
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/
static char *rcsid = "$FreeBSD: head/libexec/rtld-elf/malloc.c 154248 2006-01-12 07:28:21Z jasone $";
#endif /* LIBC_SCCS and not lint */
/*
* malloc.c (Caltech) 2/21/82
* Chris Kingsley, kingsley@cit-20.
*
* This is a very fast storage allocator. It allocates blocks of a small
* number of different sizes, and keeps free lists of each size. Blocks that
* don't exactly fit are passed up to the next larger size. In this
* implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long.
* This is designed for use in a virtual memory environment.
*/
#include <sys/types.h>
#include <err.h>
#include <paths.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/mman.h>
#include "rtld.h"
#ifdef __linux__
int
getpagesize(void)
{
return PAGE_SIZE;
}
#endif
#ifdef __FreeBSD__
#define MAP_FLAGS MAP_NOCORE|MAP_ANON
#else
#define MAP_FLAGS MAP_ANON
#endif
static void morecore();
static int findbucket();
/*
* Pre-allocate mmap'ed pages
*/
#define NPOOLPAGES (32*1024/pagesz)
static caddr_t pagepool_start, pagepool_end;
static int morepages();
/*
* The overhead on a block is at least 4 bytes. When free, this space
* contains a pointer to the next free block, and the bottom two bits must
* be zero. When in use, the first byte is set to MAGIC, and the second
* byte is the size index. The remaining bytes are for alignment.
* If range checking is enabled then a second word holds the size of the
* requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
* The order of elements is critical: ov_magic must overlay the low order
* bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
*/
union overhead {
union overhead *ov_next; /* when free */
struct {
u_char ovu_magic; /* magic number */
u_char ovu_index; /* bucket # */
#ifdef RCHECK
u_short ovu_rmagic; /* range magic number */
u_int ovu_size; /* actual block size */
#endif
} ovu;
#define ov_magic ovu.ovu_magic
#define ov_index ovu.ovu_index
#define ov_rmagic ovu.ovu_rmagic
#define ov_size ovu.ovu_size
};
#define MAGIC 0xef /* magic # on accounting info */
#define RMAGIC 0x5555 /* magic # on range info */
#ifdef RCHECK
#define RSLOP sizeof (u_short)
#else
#define RSLOP 0
#endif
/*
* nextf[i] is the pointer to the next free block of size 2^(i+3). The
* smallest allocatable block is 8 bytes. The overhead information
* precedes the data area returned to the user.
*/
#define NBUCKETS 30
static union overhead *nextf[NBUCKETS];
static int pagesz; /* page size */
static int pagebucket; /* page size bucket */
#ifdef MSTATS
/*
* nmalloc[i] is the difference between the number of mallocs and frees
* for a given block size.
*/
static u_int nmalloc[NBUCKETS];
#include <stdio.h>
#endif
#if defined(MALLOC_DEBUG) || defined(RCHECK)
#define ASSERT(p) if (!(p)) botch("p")
#include <stdio.h>
static void
botch(s)
char *s;
{
fprintf(stderr, "\r\nassertion botched: %s\r\n", s);
(void) fflush(stderr); /* just in case user buffered it */
abort();
}
#else
#define ASSERT(p)
#endif
/* Debugging stuff */
static void xprintf(const char *, ...);
#define TRACE() xprintf("TRACE %s:%d\n", __FILE__, __LINE__)
void *
malloc(nbytes)
size_t nbytes;
{
register union overhead *op;
register int bucket;
register long n;
register unsigned amt;
/*
* First time malloc is called, setup page size and
* align break pointer so all data will be page aligned.
*/
if (pagesz == 0) {
pagesz = n = getpagesize();
if (morepages(NPOOLPAGES) == 0)
return NULL;
op = (union overhead *)(pagepool_start);
n = n - sizeof (*op) - ((long)op & (n - 1));
if (n < 0)
n += pagesz;
if (n) {
pagepool_start += n;
}
bucket = 0;
amt = 8;
while ((unsigned)pagesz > amt) {
amt <<= 1;
bucket++;
}
pagebucket = bucket;
}
/*
* Convert amount of memory requested into closest block size
* stored in hash buckets which satisfies request.
* Account for space used per block for accounting.
*/
if (nbytes <= (unsigned long)(n = pagesz - sizeof (*op) - RSLOP)) {
#ifndef RCHECK
amt = 8; /* size of first bucket */
bucket = 0;
#else
amt = 16; /* size of first bucket */
bucket = 1;
#endif
n = -(sizeof (*op) + RSLOP);
} else {
amt = pagesz;
bucket = pagebucket;
}
while (nbytes > amt + n) {
amt <<= 1;
if (amt == 0)
return (NULL);
bucket++;
}
/*
* If nothing in hash bucket right now,
* request more memory from the system.
*/
if ((op = nextf[bucket]) == NULL) {
morecore(bucket);
if ((op = nextf[bucket]) == NULL)
return (NULL);
}
/* remove from linked list */
nextf[bucket] = op->ov_next;
op->ov_magic = MAGIC;
op->ov_index = bucket;
#ifdef MSTATS
nmalloc[bucket]++;
#endif
#ifdef RCHECK
/*
* Record allocated size of block and
* bound space with magic numbers.
*/
op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
op->ov_rmagic = RMAGIC;
*(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
#endif
return ((char *)(op + 1));
}
void *
calloc(size_t num, size_t size)
{
void *ret;
if (size != 0 && (num * size) / size != num) {
/* size_t overflow. */
return (NULL);
}
if ((ret = malloc(num * size)) != NULL)
memset(ret, 0, num * size);
return (ret);
}
/*
* Allocate more memory to the indicated bucket.
*/
static void
morecore(bucket)
int bucket;
{
register union overhead *op;
register int sz; /* size of desired block */
int amt; /* amount to allocate */
int nblks; /* how many blocks we get */
/*
* sbrk_size <= 0 only for big, FLUFFY, requests (about
* 2^30 bytes on a VAX, I think) or for a negative arg.
*/
sz = 1 << (bucket + 3);
#ifdef MALLOC_DEBUG
ASSERT(sz > 0);
#else
if (sz <= 0)
return;
#endif
if (sz < pagesz) {
amt = pagesz;
nblks = amt / sz;
} else {
amt = sz + pagesz;
nblks = 1;
}
if (amt > pagepool_end - pagepool_start)
if (morepages(amt/pagesz + NPOOLPAGES) == 0)
return;
op = (union overhead *)pagepool_start;
pagepool_start += amt;
/*
* Add new memory allocated to that on
* free list for this hash bucket.
*/
nextf[bucket] = op;
while (--nblks > 0) {
op->ov_next = (union overhead *)((caddr_t)op + sz);
op = (union overhead *)((caddr_t)op + sz);
}
}
void
free(void *cp)
{
register int size;
register union overhead *op;
if (cp == NULL)
return;
op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
#ifdef MALLOC_DEBUG
ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */
#else
if (op->ov_magic != MAGIC)
return; /* sanity */
#endif
#ifdef RCHECK
ASSERT(op->ov_rmagic == RMAGIC);
ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
#endif
size = op->ov_index;
ASSERT(size < NBUCKETS);
op->ov_next = nextf[size]; /* also clobbers ov_magic */
nextf[size] = op;
#ifdef MSTATS
nmalloc[size]--;
#endif
}
/*
* When a program attempts "storage compaction" as mentioned in the
* old malloc man page, it realloc's an already freed block. Usually
* this is the last block it freed; occasionally it might be farther
* back. We have to search all the free lists for the block in order
* to determine its bucket: 1st we make one pass thru the lists
* checking only the first block in each; if that fails we search
* ``realloc_srchlen'' blocks in each list for a match (the variable
* is extern so the caller can modify it). If that fails we just copy
* however many bytes was given to realloc() and hope it's not huge.
*/
int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */
void *
realloc(cp, nbytes)
void *cp;
size_t nbytes;
{
register u_int onb;
register int i;
union overhead *op;
char *res;
int was_alloced = 0;
if (cp == NULL)
return (malloc(nbytes));
op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
if (op->ov_magic == MAGIC) {
was_alloced++;
i = op->ov_index;
} else {
/*
* Already free, doing "compaction".
*
* Search for the old block of memory on the
* free list. First, check the most common
* case (last element free'd), then (this failing)
* the last ``realloc_srchlen'' items free'd.
* If all lookups fail, then assume the size of
* the memory block being realloc'd is the
* largest possible (so that all "nbytes" of new
* memory are copied into). Note that this could cause
* a memory fault if the old area was tiny, and the moon
* is gibbous. However, that is very unlikely.
*/
if ((i = findbucket(op, 1)) < 0 &&
(i = findbucket(op, realloc_srchlen)) < 0)
i = NBUCKETS;
}
onb = 1 << (i + 3);
if (onb < (u_int)pagesz)
onb -= sizeof (*op) + RSLOP;
else
onb += pagesz - sizeof (*op) - RSLOP;
/* avoid the copy if same size block */
if (was_alloced) {
if (i) {
i = 1 << (i + 2);
if (i < pagesz)
i -= sizeof (*op) + RSLOP;
else
i += pagesz - sizeof (*op) - RSLOP;
}
if (nbytes <= onb && nbytes > (size_t)i) {
#ifdef RCHECK
op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
*(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
#endif
return(cp);
} else
free(cp);
}
if ((res = malloc(nbytes)) == NULL)
return (NULL);
if (cp != res) /* common optimization if "compacting" */
bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
return (res);
}
/*
* Search ``srchlen'' elements of each free list for a block whose
* header starts at ``freep''. If srchlen is -1 search the whole list.
* Return bucket number, or -1 if not found.
*/
static int
findbucket(freep, srchlen)
union overhead *freep;
int srchlen;
{
register union overhead *p;
register int i, j;
for (i = 0; i < NBUCKETS; i++) {
j = 0;
for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
if (p == freep)
return (i);
j++;
}
}
return (-1);
}
#ifdef MSTATS
/*
* mstats - print out statistics about malloc
*
* Prints two lines of numbers, one showing the length of the free list
* for each size category, the second showing the number of mallocs -
* frees for each size category.
*/
mstats(s)
char *s;
{
register int i, j;
register union overhead *p;
int totfree = 0,
totused = 0;
fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
for (i = 0; i < NBUCKETS; i++) {
for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
;
fprintf(stderr, " %d", j);
totfree += j * (1 << (i + 3));
}
fprintf(stderr, "\nused:\t");
for (i = 0; i < NBUCKETS; i++) {
fprintf(stderr, " %d", nmalloc[i]);
totused += nmalloc[i] * (1 << (i + 3));
}
fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
totused, totfree);
}
#endif
static int
morepages(n)
int n;
{
int fd = -1;
int offset;
if (pagepool_end - pagepool_start > pagesz) {
caddr_t addr = (caddr_t)
(((long)pagepool_start + pagesz - 1) & ~(pagesz - 1));
if (munmap(addr, pagepool_end - addr) != 0)
warn("morepages: munmap %p", addr);
}
offset = (long)pagepool_start - ((long)pagepool_start & ~(pagesz - 1));
if ((pagepool_start = mmap(0, n * pagesz,
PROT_READ|PROT_WRITE,
MAP_FLAGS|MAP_PRIVATE, fd, 0)) == (caddr_t)-1) {
xprintf("Cannot map anonymous memory");
return 0;
}
pagepool_end = pagepool_start + n * pagesz;
pagepool_start += offset;
return n;
}
/*
* Non-mallocing printf, for use by malloc itself.
*/
static void
xprintf(const char *fmt, ...)
{
char buf[256];
va_list ap;
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
(void)write(STDOUT_FILENO, buf, strlen(buf));
va_end(ap);
}

View File

@ -1,69 +0,0 @@
/*-
* Copyright (c) 2004 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/rtld_tls.h 133063 2004-08-03 08:51:00Z dfr $
*/
/*
* Semi-public interface from thread libraries to rtld for managing
* TLS.
*/
#ifndef _RTLD_TLS_H_
#define _RTLD_TLS_H_
/*
* Allocate a TLS block for a new thread. The memory allocated will
* include 'tcbsize' bytes aligned to a 'tcbalign' boundary (in bytes)
* for the thread library's private purposes. The location of the TCB
* block is returned by this function. For architectures using
* 'Variant I' TLS, the thread local storage follows the TCB, and for
* 'Variant II', the thread local storage precedes it. For
* architectures using the 'Variant II' model (e.g. i386, amd64,
* sparc64), the TCB must begin with two pointer fields which are used
* by rtld for its TLS implementation. For the 'Variant I' model, the
* TCB must begin with a single pointer field for rtld's
* implementation.
*
* If the value of 'oldtls' is non-NULL, the new TLS block will be
* initialised using the values contained in 'oldtls' and 'oldtls'
* will be freed. This is typically used when initialising a thread
* library to migrate from using the initial bootstrap TLS block
* created by rtld to one which contains suitable thread library
* private data.
*
* The value returned from this function is suitable for installing
* directly into the thread pointer register.
*/
extern void *_rtld_allocate_tls(void* oldtls, size_t tcbsize, size_t tcbalign);
/*
* Free a TLS block allocated using _rtld_allocate_tls(). The tcbsize
* and tcbalign parameters must be the same as those used to allocate
* the block.
*/
extern void _rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign);
#endif

View File

@ -1,60 +0,0 @@
/*-
* Copyright 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/libexec/rtld-elf/xmalloc.c 116568 2003-06-19 05:28:26Z mdodd $
*/
#include <err.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "rtld.h"
void *xcalloc(size_t);
void *xmalloc(size_t);
char *xstrdup(const char *);
void *
xcalloc(size_t size)
{
return memset(xmalloc(size), 0, size);
}
void *
xmalloc(size_t size)
{
void *p = malloc(size);
if (p == NULL)
err(1, "Out of memory");
return p;
}
char *
xstrdup(const char *s)
{
char *p = strdup(s);
if (p == NULL)
err(1, "Out of memory");
return p;
}