mirror of
https://github.com/rapid7/metasploit-payloads
synced 2024-11-26 17:41:08 +01:00
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:
parent
4b10b7b0ee
commit
c5048a1643
@ -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
|
@ -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 $\"");
|
@ -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"
|
@ -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"
|
@ -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 . */
|
||||
}
|
@ -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);
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
||||
};
|
@ -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 */
|
@ -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_ */
|
@ -1,6 +0,0 @@
|
||||
.globl call_late_start
|
||||
|
||||
call_late_start:
|
||||
add $0x4, %esp
|
||||
popl %eax
|
||||
jmp *%eax
|
@ -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);
|
||||
}
|
@ -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
|
@ -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
|
@ -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_ */
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
@ -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]);
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user