├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── NEWS ├── README ├── configure.ac ├── scripts ├── 0x18000000.solaris.map ├── depcomp ├── install-sh ├── lean.m4 └── missing ├── src ├── Makefile.am ├── bbuffer.c ├── bbuffer.h ├── dlfcn.c ├── elfload-ld.c ├── elfload.c ├── elfload.h ├── elfload_dlfcn.h ├── elfload_elf.h ├── elfload_exec.h ├── elfnative.h ├── main.c ├── whereami.c └── whereami.h └── test ├── common ├── Makefile ├── libc_wrap.c └── testdl.c ├── i686-pc-linux-gnu ├── Makefile ├── libc_wrap.c ├── testdl ├── testdl.c ├── testhost ├── testhost.s ├── testso.s ├── testso.so ├── teststatic └── teststatic.s └── x86_64-pc-linux-gnu ├── Makefile ├── libc_wrap.c ├── testdl ├── testdl.c ├── testhost ├── testhost.s ├── testso.s ├── testso.so ├── teststatic └── teststatic.s /AUTHORS: -------------------------------------------------------------------------------- 1 | gelfload was written by Gregor Richards. 2 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Unless otherwise noted, every file in this distribution is under this license: 2 | 3 | Copyright (c) 2008 Gregor Richards 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | 24 | Please note that elf.h is taken from GNU libc, and so is under the GNU Lesser 25 | General Public License. This means that elfload as a whole must be distributed 26 | under the terms of the LGPL. 27 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 5 | 2006 Free Software Foundation, Inc. 6 | 7 | This file is free documentation; the Free Software Foundation gives 8 | unlimited permission to copy, distribute and modify it. 9 | 10 | Basic Installation 11 | ================== 12 | 13 | Briefly, the shell commands `./configure; make; make install' should 14 | configure, build, and install this package. The following 15 | more-detailed instructions are generic; see the `README' file for 16 | instructions specific to this package. 17 | 18 | The `configure' shell script attempts to guess correct values for 19 | various system-dependent variables used during compilation. It uses 20 | those values to create a `Makefile' in each directory of the package. 21 | It may also create one or more `.h' files containing system-dependent 22 | definitions. Finally, it creates a shell script `config.status' that 23 | you can run in the future to recreate the current configuration, and a 24 | file `config.log' containing compiler output (useful mainly for 25 | debugging `configure'). 26 | 27 | It can also use an optional file (typically called `config.cache' 28 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 29 | the results of its tests to speed up reconfiguring. Caching is 30 | disabled by default to prevent problems with accidental use of stale 31 | cache files. 32 | 33 | If you need to do unusual things to compile the package, please try 34 | to figure out how `configure' could check whether to do them, and mail 35 | diffs or instructions to the address given in the `README' so they can 36 | be considered for the next release. If you are using the cache, and at 37 | some point `config.cache' contains results you don't want to keep, you 38 | may remove or edit it. 39 | 40 | The file `configure.ac' (or `configure.in') is used to create 41 | `configure' by a program called `autoconf'. You need `configure.ac' if 42 | you want to change it or regenerate `configure' using a newer version 43 | of `autoconf'. 44 | 45 | The simplest way to compile this package is: 46 | 47 | 1. `cd' to the directory containing the package's source code and type 48 | `./configure' to configure the package for your system. 49 | 50 | Running `configure' might take a while. While running, it prints 51 | some messages telling which features it is checking for. 52 | 53 | 2. Type `make' to compile the package. 54 | 55 | 3. Optionally, type `make check' to run any self-tests that come with 56 | the package. 57 | 58 | 4. Type `make install' to install the programs and any data files and 59 | documentation. 60 | 61 | 5. You can remove the program binaries and object files from the 62 | source code directory by typing `make clean'. To also remove the 63 | files that `configure' created (so you can compile the package for 64 | a different kind of computer), type `make distclean'. There is 65 | also a `make maintainer-clean' target, but that is intended mainly 66 | for the package's developers. If you use it, you may have to get 67 | all sorts of other programs in order to regenerate files that came 68 | with the distribution. 69 | 70 | Compilers and Options 71 | ===================== 72 | 73 | Some systems require unusual options for compilation or linking that the 74 | `configure' script does not know about. Run `./configure --help' for 75 | details on some of the pertinent environment variables. 76 | 77 | You can give `configure' initial values for configuration parameters 78 | by setting variables in the command line or in the environment. Here 79 | is an example: 80 | 81 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 82 | 83 | *Note Defining Variables::, for more details. 84 | 85 | Compiling For Multiple Architectures 86 | ==================================== 87 | 88 | You can compile the package for more than one kind of computer at the 89 | same time, by placing the object files for each architecture in their 90 | own directory. To do this, you can use GNU `make'. `cd' to the 91 | directory where you want the object files and executables to go and run 92 | the `configure' script. `configure' automatically checks for the 93 | source code in the directory that `configure' is in and in `..'. 94 | 95 | With a non-GNU `make', it is safer to compile the package for one 96 | architecture at a time in the source code directory. After you have 97 | installed the package for one architecture, use `make distclean' before 98 | reconfiguring for another architecture. 99 | 100 | Installation Names 101 | ================== 102 | 103 | By default, `make install' installs the package's commands under 104 | `/usr/local/bin', include files under `/usr/local/include', etc. You 105 | can specify an installation prefix other than `/usr/local' by giving 106 | `configure' the option `--prefix=PREFIX'. 107 | 108 | You can specify separate installation prefixes for 109 | architecture-specific files and architecture-independent files. If you 110 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 111 | PREFIX as the prefix for installing programs and libraries. 112 | Documentation and other data files still use the regular prefix. 113 | 114 | In addition, if you use an unusual directory layout you can give 115 | options like `--bindir=DIR' to specify different values for particular 116 | kinds of files. Run `configure --help' for a list of the directories 117 | you can set and what kinds of files go in them. 118 | 119 | If the package supports it, you can cause programs to be installed 120 | with an extra prefix or suffix on their names by giving `configure' the 121 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 122 | 123 | Optional Features 124 | ================= 125 | 126 | Some packages pay attention to `--enable-FEATURE' options to 127 | `configure', where FEATURE indicates an optional part of the package. 128 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 129 | is something like `gnu-as' or `x' (for the X Window System). The 130 | `README' should mention any `--enable-' and `--with-' options that the 131 | package recognizes. 132 | 133 | For packages that use the X Window System, `configure' can usually 134 | find the X include and library files automatically, but if it doesn't, 135 | you can use the `configure' options `--x-includes=DIR' and 136 | `--x-libraries=DIR' to specify their locations. 137 | 138 | Specifying the System Type 139 | ========================== 140 | 141 | There may be some features `configure' cannot figure out automatically, 142 | but needs to determine by the type of machine the package will run on. 143 | Usually, assuming the package is built to be run on the _same_ 144 | architectures, `configure' can figure that out, but if it prints a 145 | message saying it cannot guess the machine type, give it the 146 | `--build=TYPE' option. TYPE can either be a short name for the system 147 | type, such as `sun4', or a canonical name which has the form: 148 | 149 | CPU-COMPANY-SYSTEM 150 | 151 | where SYSTEM can have one of these forms: 152 | 153 | OS KERNEL-OS 154 | 155 | See the file `config.sub' for the possible values of each field. If 156 | `config.sub' isn't included in this package, then this package doesn't 157 | need to know the machine type. 158 | 159 | If you are _building_ compiler tools for cross-compiling, you should 160 | use the option `--target=TYPE' to select the type of system they will 161 | produce code for. 162 | 163 | If you want to _use_ a cross compiler, that generates code for a 164 | platform different from the build platform, you should specify the 165 | "host" platform (i.e., that on which the generated programs will 166 | eventually be run) with `--host=TYPE'. 167 | 168 | Sharing Defaults 169 | ================ 170 | 171 | If you want to set default values for `configure' scripts to share, you 172 | can create a site shell script called `config.site' that gives default 173 | values for variables like `CC', `cache_file', and `prefix'. 174 | `configure' looks for `PREFIX/share/config.site' if it exists, then 175 | `PREFIX/etc/config.site' if it exists. Or, you can set the 176 | `CONFIG_SITE' environment variable to the location of the site script. 177 | A warning: not all `configure' scripts look for a site script. 178 | 179 | Defining Variables 180 | ================== 181 | 182 | Variables not defined in a site shell script can be set in the 183 | environment passed to `configure'. However, some packages may run 184 | configure again during the build, and the customized values of these 185 | variables may be lost. In order to avoid this problem, you should set 186 | them in the `configure' command line, using `VAR=value'. For example: 187 | 188 | ./configure CC=/usr/local2/bin/gcc 189 | 190 | causes the specified `gcc' to be used as the C compiler (unless it is 191 | overridden in the site shell script). 192 | 193 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 194 | an Autoconf bug. Until the bug is fixed you can use this workaround: 195 | 196 | CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash 197 | 198 | `configure' Invocation 199 | ====================== 200 | 201 | `configure' recognizes the following options to control how it operates. 202 | 203 | `--help' 204 | `-h' 205 | Print a summary of the options to `configure', and exit. 206 | 207 | `--version' 208 | `-V' 209 | Print the version of Autoconf used to generate the `configure' 210 | script, and exit. 211 | 212 | `--cache-file=FILE' 213 | Enable the cache: use and save the results of the tests in FILE, 214 | traditionally `config.cache'. FILE defaults to `/dev/null' to 215 | disable caching. 216 | 217 | `--config-cache' 218 | `-C' 219 | Alias for `--cache-file=config.cache'. 220 | 221 | `--quiet' 222 | `--silent' 223 | `-q' 224 | Do not print messages saying which checks are being made. To 225 | suppress all normal output, redirect it to `/dev/null' (any error 226 | messages will still be shown). 227 | 228 | `--srcdir=DIR' 229 | Look for the package's source code in directory DIR. Usually 230 | `configure' can determine that directory automatically. 231 | 232 | `configure' also accepts some other, not widely useful, options. Run 233 | `configure --help' for more details. 234 | 235 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src 2 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | None yet. 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is gelfload, a portable runtime ELF loader. It lets you use ELF on 2 | platforms that don't natively support ELF! 3 | 4 | Some special properties of gelfload: 5 | 6 | * To integrate gelfload well into platforms that /do/ support ELF, gelfload 7 | ELF files should have their interpreter set to /usr/bin/gelfload-ld 8 | 9 | * gelfload ELF files may refer to gelfload .so files by their standard name, 10 | or they may use symbolic names to refer to host libraries: 11 | * libhost_ refers to the library on the host, e.g. 12 | libhost_libc.so.6 or libhost_msvcrt.dll 13 | * libhost_.so refers to: 14 | * if possible, all libraries loaded by gelfload in the host, including 15 | certainly at least libc 16 | * otherwise, libc or the nearest equivalent, e.g. msvcrt.dll 17 | * libloader_dl.0 refers to the loader's builtin library providing dlopen() 18 | and dlsym() 19 | 20 | gelfload is still in development, and doesn't yet support all ELF relocations. 21 | Some tests are in test/. They're tested primarily on GNU/Linux, however the 22 | test named testdl uses only standard libc functions and should work on any host 23 | system (including e.g. Mac OS X). 24 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.60) 5 | AC_INIT([gelfload], [1], [cdgregorr@sourceforge.net]) 6 | AC_CONFIG_SRCDIR([src/elfload.h]) 7 | AC_CONFIG_HEADER([config.h]) 8 | AC_CONFIG_AUX_DIR([scripts]) 9 | 10 | m4_include([scripts/lean.m4]) 11 | AM_INIT_AUTOMAKE 12 | 13 | # Checks for programs. 14 | AC_PROG_CC 15 | AC_PROG_RANLIB 16 | AC_PROG_LN_S 17 | 18 | # Checks for libraries. 19 | AC_CHECK_LIB([dl], [dlopen], [ 20 | AC_DEFINE([HAVE_LIBDL], 1, [Defined if libdl is available.]) 21 | HAVE_LIBDL=true 22 | ], [ 23 | HAVE_LIBDL=false 24 | ]) 25 | AM_CONDITIONAL(HAVE_LIBDL, test "x$HAVE_LIBDL" = "xtrue") 26 | 27 | # Check if we can rebase the program at 0x18000000 28 | ORIG_LDFLAGS="$LDFLAGS" 29 | LDFLAGS="$LDFLAGS -Wl,--image-base,0x18000000" 30 | export LDFLAGS 31 | AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [], [ 32 | # OK, try with --section-start. This test comes second because MingW allows 33 | # it, though it doesn't work 34 | LDFLAGS="$ORIG_LDFLAGS -Wl,--section-start,.dynsym=0x19000000 -Wl,--section-start,.hash=0x18000000" 35 | export LDFLAGS 36 | AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [], [ 37 | # Maybe we're using a Solaris-style linker, let's try a map file 38 | srcdir_absolute=`cd "$srcdir" && pwd` 39 | LDFLAGS="$ORIG_LDFLAGS -Wl,-M$srcdir_absolute/scripts/0x18000000.solaris.map" 40 | export LDFLAGS 41 | AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [], [ 42 | # Too bad, this can't be done 43 | LDFLAGS="$ORIG_LDFLAGS" 44 | export LDFLAGS 45 | ]) 46 | ]) 47 | ]) 48 | 49 | # Checks for header files. 50 | AC_CHECK_HEADERS([dlfcn.h]) 51 | 52 | # Checks for typedefs, structures, and compiler characteristics. 53 | AC_CHECK_SIZEOF([void *]) 54 | 55 | # -static 56 | ORIG_LDFLAGS="$LDFLAGS" 57 | LDFLAGS="$LDFLAGS -static" 58 | AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [ 59 | HAVE_STATIC=yes 60 | ], [ 61 | HAVE_STATIC=no 62 | ]) 63 | LDFLAGS="$ORIG_LDFLAGS" 64 | AM_CONDITIONAL(HAVE_STATIC, test x$HAVE_STATIC = xyes) 65 | 66 | # architecture 67 | AC_LANG([C]) 68 | AC_DEFUN([ACX_ARCH_CHECK], [ 69 | AC_COMPILE_IFELSE([ 70 | AC_LANG_PROGRAM([ 71 | #if !($1) 72 | @syntax_error@ 73 | #endif 74 | ], []) 75 | ], [ 76 | AC_SUBST([GELFLOAD_ARCH], [$2]) 77 | AC_DEFINE([GELFLOAD_ARCH_[]$2], [1], [Define if architecture is $2.]) 78 | ], [$3]) 79 | ]) 80 | 81 | ACX_ARCH_CHECK([defined(__x86_64__) || defined(__x86_64) || defined(_M_X64)], 82 | [x86_64], [ 83 | ACX_ARCH_CHECK([defined(__i386__) || defined(__i386) || defined(_M_IX86)], 84 | [i386]) 85 | ]) 86 | 87 | # Checks for library functions. 88 | AC_CHECK_FUNCS([mmap]) 89 | 90 | # Prefix for elfload-ld.c to know where the main program is: 91 | AC_DEFINE_UNQUOTED([PREFIX], ["$prefix"], [Install prefix]) 92 | 93 | AC_CONFIG_FILES([Makefile 94 | src/Makefile]) 95 | AC_OUTPUT 96 | -------------------------------------------------------------------------------- /scripts/0x18000000.solaris.map: -------------------------------------------------------------------------------- 1 | $mapfile_version 2 2 | LOAD_SEGMENT text { VADDR = 0x18000000 }; 3 | -------------------------------------------------------------------------------- /scripts/depcomp: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # depcomp - compile a program generating dependencies as side-effects 3 | 4 | scriptversion=2006-10-15.18 5 | 6 | # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006 Free Software 7 | # Foundation, Inc. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program; if not, write to the Free Software 21 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 22 | # 02110-1301, USA. 23 | 24 | # As a special exception to the GNU General Public License, if you 25 | # distribute this file as part of a program that contains a 26 | # configuration script generated by Autoconf, you may include it under 27 | # the same distribution terms that you use for the rest of that program. 28 | 29 | # Originally written by Alexandre Oliva . 30 | 31 | case $1 in 32 | '') 33 | echo "$0: No command. Try \`$0 --help' for more information." 1>&2 34 | exit 1; 35 | ;; 36 | -h | --h*) 37 | cat <<\EOF 38 | Usage: depcomp [--help] [--version] PROGRAM [ARGS] 39 | 40 | Run PROGRAMS ARGS to compile a file, generating dependencies 41 | as side-effects. 42 | 43 | Environment variables: 44 | depmode Dependency tracking mode. 45 | source Source file read by `PROGRAMS ARGS'. 46 | object Object file output by `PROGRAMS ARGS'. 47 | DEPDIR directory where to store dependencies. 48 | depfile Dependency file to output. 49 | tmpdepfile Temporary file to use when outputing dependencies. 50 | libtool Whether libtool is used (yes/no). 51 | 52 | Report bugs to . 53 | EOF 54 | exit $? 55 | ;; 56 | -v | --v*) 57 | echo "depcomp $scriptversion" 58 | exit $? 59 | ;; 60 | esac 61 | 62 | if test -z "$depmode" || test -z "$source" || test -z "$object"; then 63 | echo "depcomp: Variables source, object and depmode must be set" 1>&2 64 | exit 1 65 | fi 66 | 67 | # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. 68 | depfile=${depfile-`echo "$object" | 69 | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} 70 | tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} 71 | 72 | rm -f "$tmpdepfile" 73 | 74 | # Some modes work just like other modes, but use different flags. We 75 | # parameterize here, but still list the modes in the big case below, 76 | # to make depend.m4 easier to write. Note that we *cannot* use a case 77 | # here, because this file can only contain one case statement. 78 | if test "$depmode" = hp; then 79 | # HP compiler uses -M and no extra arg. 80 | gccflag=-M 81 | depmode=gcc 82 | fi 83 | 84 | if test "$depmode" = dashXmstdout; then 85 | # This is just like dashmstdout with a different argument. 86 | dashmflag=-xM 87 | depmode=dashmstdout 88 | fi 89 | 90 | case "$depmode" in 91 | gcc3) 92 | ## gcc 3 implements dependency tracking that does exactly what 93 | ## we want. Yay! Note: for some reason libtool 1.4 doesn't like 94 | ## it if -MD -MP comes after the -MF stuff. Hmm. 95 | ## Unfortunately, FreeBSD c89 acceptance of flags depends upon 96 | ## the command line argument order; so add the flags where they 97 | ## appear in depend2.am. Note that the slowdown incurred here 98 | ## affects only configure: in makefiles, %FASTDEP% shortcuts this. 99 | for arg 100 | do 101 | case $arg in 102 | -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; 103 | *) set fnord "$@" "$arg" ;; 104 | esac 105 | shift # fnord 106 | shift # $arg 107 | done 108 | "$@" 109 | stat=$? 110 | if test $stat -eq 0; then : 111 | else 112 | rm -f "$tmpdepfile" 113 | exit $stat 114 | fi 115 | mv "$tmpdepfile" "$depfile" 116 | ;; 117 | 118 | gcc) 119 | ## There are various ways to get dependency output from gcc. Here's 120 | ## why we pick this rather obscure method: 121 | ## - Don't want to use -MD because we'd like the dependencies to end 122 | ## up in a subdir. Having to rename by hand is ugly. 123 | ## (We might end up doing this anyway to support other compilers.) 124 | ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like 125 | ## -MM, not -M (despite what the docs say). 126 | ## - Using -M directly means running the compiler twice (even worse 127 | ## than renaming). 128 | if test -z "$gccflag"; then 129 | gccflag=-MD, 130 | fi 131 | "$@" -Wp,"$gccflag$tmpdepfile" 132 | stat=$? 133 | if test $stat -eq 0; then : 134 | else 135 | rm -f "$tmpdepfile" 136 | exit $stat 137 | fi 138 | rm -f "$depfile" 139 | echo "$object : \\" > "$depfile" 140 | alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 141 | ## The second -e expression handles DOS-style file names with drive letters. 142 | sed -e 's/^[^:]*: / /' \ 143 | -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" 144 | ## This next piece of magic avoids the `deleted header file' problem. 145 | ## The problem is that when a header file which appears in a .P file 146 | ## is deleted, the dependency causes make to die (because there is 147 | ## typically no way to rebuild the header). We avoid this by adding 148 | ## dummy dependencies for each header file. Too bad gcc doesn't do 149 | ## this for us directly. 150 | tr ' ' ' 151 | ' < "$tmpdepfile" | 152 | ## Some versions of gcc put a space before the `:'. On the theory 153 | ## that the space means something, we add a space to the output as 154 | ## well. 155 | ## Some versions of the HPUX 10.20 sed can't process this invocation 156 | ## correctly. Breaking it into two sed invocations is a workaround. 157 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 158 | rm -f "$tmpdepfile" 159 | ;; 160 | 161 | hp) 162 | # This case exists only to let depend.m4 do its work. It works by 163 | # looking at the text of this script. This case will never be run, 164 | # since it is checked for above. 165 | exit 1 166 | ;; 167 | 168 | sgi) 169 | if test "$libtool" = yes; then 170 | "$@" "-Wp,-MDupdate,$tmpdepfile" 171 | else 172 | "$@" -MDupdate "$tmpdepfile" 173 | fi 174 | stat=$? 175 | if test $stat -eq 0; then : 176 | else 177 | rm -f "$tmpdepfile" 178 | exit $stat 179 | fi 180 | rm -f "$depfile" 181 | 182 | if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files 183 | echo "$object : \\" > "$depfile" 184 | 185 | # Clip off the initial element (the dependent). Don't try to be 186 | # clever and replace this with sed code, as IRIX sed won't handle 187 | # lines with more than a fixed number of characters (4096 in 188 | # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; 189 | # the IRIX cc adds comments like `#:fec' to the end of the 190 | # dependency line. 191 | tr ' ' ' 192 | ' < "$tmpdepfile" \ 193 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ 194 | tr ' 195 | ' ' ' >> $depfile 196 | echo >> $depfile 197 | 198 | # The second pass generates a dummy entry for each header file. 199 | tr ' ' ' 200 | ' < "$tmpdepfile" \ 201 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ 202 | >> $depfile 203 | else 204 | # The sourcefile does not contain any dependencies, so just 205 | # store a dummy comment line, to avoid errors with the Makefile 206 | # "include basename.Plo" scheme. 207 | echo "#dummy" > "$depfile" 208 | fi 209 | rm -f "$tmpdepfile" 210 | ;; 211 | 212 | aix) 213 | # The C for AIX Compiler uses -M and outputs the dependencies 214 | # in a .u file. In older versions, this file always lives in the 215 | # current directory. Also, the AIX compiler puts `$object:' at the 216 | # start of each line; $object doesn't have directory information. 217 | # Version 6 uses the directory in both cases. 218 | stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` 219 | tmpdepfile="$stripped.u" 220 | if test "$libtool" = yes; then 221 | "$@" -Wc,-M 222 | else 223 | "$@" -M 224 | fi 225 | stat=$? 226 | 227 | if test -f "$tmpdepfile"; then : 228 | else 229 | stripped=`echo "$stripped" | sed 's,^.*/,,'` 230 | tmpdepfile="$stripped.u" 231 | fi 232 | 233 | if test $stat -eq 0; then : 234 | else 235 | rm -f "$tmpdepfile" 236 | exit $stat 237 | fi 238 | 239 | if test -f "$tmpdepfile"; then 240 | outname="$stripped.o" 241 | # Each line is of the form `foo.o: dependent.h'. 242 | # Do two passes, one to just change these to 243 | # `$object: dependent.h' and one to simply `dependent.h:'. 244 | sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" 245 | sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" 246 | else 247 | # The sourcefile does not contain any dependencies, so just 248 | # store a dummy comment line, to avoid errors with the Makefile 249 | # "include basename.Plo" scheme. 250 | echo "#dummy" > "$depfile" 251 | fi 252 | rm -f "$tmpdepfile" 253 | ;; 254 | 255 | icc) 256 | # Intel's C compiler understands `-MD -MF file'. However on 257 | # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c 258 | # ICC 7.0 will fill foo.d with something like 259 | # foo.o: sub/foo.c 260 | # foo.o: sub/foo.h 261 | # which is wrong. We want: 262 | # sub/foo.o: sub/foo.c 263 | # sub/foo.o: sub/foo.h 264 | # sub/foo.c: 265 | # sub/foo.h: 266 | # ICC 7.1 will output 267 | # foo.o: sub/foo.c sub/foo.h 268 | # and will wrap long lines using \ : 269 | # foo.o: sub/foo.c ... \ 270 | # sub/foo.h ... \ 271 | # ... 272 | 273 | "$@" -MD -MF "$tmpdepfile" 274 | stat=$? 275 | if test $stat -eq 0; then : 276 | else 277 | rm -f "$tmpdepfile" 278 | exit $stat 279 | fi 280 | rm -f "$depfile" 281 | # Each line is of the form `foo.o: dependent.h', 282 | # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. 283 | # Do two passes, one to just change these to 284 | # `$object: dependent.h' and one to simply `dependent.h:'. 285 | sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" 286 | # Some versions of the HPUX 10.20 sed can't process this invocation 287 | # correctly. Breaking it into two sed invocations is a workaround. 288 | sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | 289 | sed -e 's/$/ :/' >> "$depfile" 290 | rm -f "$tmpdepfile" 291 | ;; 292 | 293 | hp2) 294 | # The "hp" stanza above does not work with aCC (C++) and HP's ia64 295 | # compilers, which have integrated preprocessors. The correct option 296 | # to use with these is +Maked; it writes dependencies to a file named 297 | # 'foo.d', which lands next to the object file, wherever that 298 | # happens to be. 299 | # Much of this is similar to the tru64 case; see comments there. 300 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 301 | test "x$dir" = "x$object" && dir= 302 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 303 | if test "$libtool" = yes; then 304 | tmpdepfile1=$dir$base.d 305 | tmpdepfile2=$dir.libs/$base.d 306 | "$@" -Wc,+Maked 307 | else 308 | tmpdepfile1=$dir$base.d 309 | tmpdepfile2=$dir$base.d 310 | "$@" +Maked 311 | fi 312 | stat=$? 313 | if test $stat -eq 0; then : 314 | else 315 | rm -f "$tmpdepfile1" "$tmpdepfile2" 316 | exit $stat 317 | fi 318 | 319 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" 320 | do 321 | test -f "$tmpdepfile" && break 322 | done 323 | if test -f "$tmpdepfile"; then 324 | sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" 325 | # Add `dependent.h:' lines. 326 | sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" 327 | else 328 | echo "#dummy" > "$depfile" 329 | fi 330 | rm -f "$tmpdepfile" "$tmpdepfile2" 331 | ;; 332 | 333 | tru64) 334 | # The Tru64 compiler uses -MD to generate dependencies as a side 335 | # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. 336 | # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 337 | # dependencies in `foo.d' instead, so we check for that too. 338 | # Subdirectories are respected. 339 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 340 | test "x$dir" = "x$object" && dir= 341 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 342 | 343 | if test "$libtool" = yes; then 344 | # With Tru64 cc, shared objects can also be used to make a 345 | # static library. This mechanism is used in libtool 1.4 series to 346 | # handle both shared and static libraries in a single compilation. 347 | # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. 348 | # 349 | # With libtool 1.5 this exception was removed, and libtool now 350 | # generates 2 separate objects for the 2 libraries. These two 351 | # compilations output dependencies in $dir.libs/$base.o.d and 352 | # in $dir$base.o.d. We have to check for both files, because 353 | # one of the two compilations can be disabled. We should prefer 354 | # $dir$base.o.d over $dir.libs/$base.o.d because the latter is 355 | # automatically cleaned when .libs/ is deleted, while ignoring 356 | # the former would cause a distcleancheck panic. 357 | tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 358 | tmpdepfile2=$dir$base.o.d # libtool 1.5 359 | tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 360 | tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 361 | "$@" -Wc,-MD 362 | else 363 | tmpdepfile1=$dir$base.o.d 364 | tmpdepfile2=$dir$base.d 365 | tmpdepfile3=$dir$base.d 366 | tmpdepfile4=$dir$base.d 367 | "$@" -MD 368 | fi 369 | 370 | stat=$? 371 | if test $stat -eq 0; then : 372 | else 373 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" 374 | exit $stat 375 | fi 376 | 377 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" 378 | do 379 | test -f "$tmpdepfile" && break 380 | done 381 | if test -f "$tmpdepfile"; then 382 | sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" 383 | # That's a tab and a space in the []. 384 | sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" 385 | else 386 | echo "#dummy" > "$depfile" 387 | fi 388 | rm -f "$tmpdepfile" 389 | ;; 390 | 391 | #nosideeffect) 392 | # This comment above is used by automake to tell side-effect 393 | # dependency tracking mechanisms from slower ones. 394 | 395 | dashmstdout) 396 | # Important note: in order to support this mode, a compiler *must* 397 | # always write the preprocessed file to stdout, regardless of -o. 398 | "$@" || exit $? 399 | 400 | # Remove the call to Libtool. 401 | if test "$libtool" = yes; then 402 | while test $1 != '--mode=compile'; do 403 | shift 404 | done 405 | shift 406 | fi 407 | 408 | # Remove `-o $object'. 409 | IFS=" " 410 | for arg 411 | do 412 | case $arg in 413 | -o) 414 | shift 415 | ;; 416 | $object) 417 | shift 418 | ;; 419 | *) 420 | set fnord "$@" "$arg" 421 | shift # fnord 422 | shift # $arg 423 | ;; 424 | esac 425 | done 426 | 427 | test -z "$dashmflag" && dashmflag=-M 428 | # Require at least two characters before searching for `:' 429 | # in the target name. This is to cope with DOS-style filenames: 430 | # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. 431 | "$@" $dashmflag | 432 | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" 433 | rm -f "$depfile" 434 | cat < "$tmpdepfile" > "$depfile" 435 | tr ' ' ' 436 | ' < "$tmpdepfile" | \ 437 | ## Some versions of the HPUX 10.20 sed can't process this invocation 438 | ## correctly. Breaking it into two sed invocations is a workaround. 439 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 440 | rm -f "$tmpdepfile" 441 | ;; 442 | 443 | dashXmstdout) 444 | # This case only exists to satisfy depend.m4. It is never actually 445 | # run, as this mode is specially recognized in the preamble. 446 | exit 1 447 | ;; 448 | 449 | makedepend) 450 | "$@" || exit $? 451 | # Remove any Libtool call 452 | if test "$libtool" = yes; then 453 | while test $1 != '--mode=compile'; do 454 | shift 455 | done 456 | shift 457 | fi 458 | # X makedepend 459 | shift 460 | cleared=no 461 | for arg in "$@"; do 462 | case $cleared in 463 | no) 464 | set ""; shift 465 | cleared=yes ;; 466 | esac 467 | case "$arg" in 468 | -D*|-I*) 469 | set fnord "$@" "$arg"; shift ;; 470 | # Strip any option that makedepend may not understand. Remove 471 | # the object too, otherwise makedepend will parse it as a source file. 472 | -*|$object) 473 | ;; 474 | *) 475 | set fnord "$@" "$arg"; shift ;; 476 | esac 477 | done 478 | obj_suffix="`echo $object | sed 's/^.*\././'`" 479 | touch "$tmpdepfile" 480 | ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" 481 | rm -f "$depfile" 482 | cat < "$tmpdepfile" > "$depfile" 483 | sed '1,2d' "$tmpdepfile" | tr ' ' ' 484 | ' | \ 485 | ## Some versions of the HPUX 10.20 sed can't process this invocation 486 | ## correctly. Breaking it into two sed invocations is a workaround. 487 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 488 | rm -f "$tmpdepfile" "$tmpdepfile".bak 489 | ;; 490 | 491 | cpp) 492 | # Important note: in order to support this mode, a compiler *must* 493 | # always write the preprocessed file to stdout. 494 | "$@" || exit $? 495 | 496 | # Remove the call to Libtool. 497 | if test "$libtool" = yes; then 498 | while test $1 != '--mode=compile'; do 499 | shift 500 | done 501 | shift 502 | fi 503 | 504 | # Remove `-o $object'. 505 | IFS=" " 506 | for arg 507 | do 508 | case $arg in 509 | -o) 510 | shift 511 | ;; 512 | $object) 513 | shift 514 | ;; 515 | *) 516 | set fnord "$@" "$arg" 517 | shift # fnord 518 | shift # $arg 519 | ;; 520 | esac 521 | done 522 | 523 | "$@" -E | 524 | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ 525 | -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | 526 | sed '$ s: \\$::' > "$tmpdepfile" 527 | rm -f "$depfile" 528 | echo "$object : \\" > "$depfile" 529 | cat < "$tmpdepfile" >> "$depfile" 530 | sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" 531 | rm -f "$tmpdepfile" 532 | ;; 533 | 534 | msvisualcpp) 535 | # Important note: in order to support this mode, a compiler *must* 536 | # always write the preprocessed file to stdout, regardless of -o, 537 | # because we must use -o when running libtool. 538 | "$@" || exit $? 539 | IFS=" " 540 | for arg 541 | do 542 | case "$arg" in 543 | "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") 544 | set fnord "$@" 545 | shift 546 | shift 547 | ;; 548 | *) 549 | set fnord "$@" "$arg" 550 | shift 551 | shift 552 | ;; 553 | esac 554 | done 555 | "$@" -E | 556 | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" 557 | rm -f "$depfile" 558 | echo "$object : \\" > "$depfile" 559 | . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" 560 | echo " " >> "$depfile" 561 | . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" 562 | rm -f "$tmpdepfile" 563 | ;; 564 | 565 | none) 566 | exec "$@" 567 | ;; 568 | 569 | *) 570 | echo "Unknown depmode $depmode" 1>&2 571 | exit 1 572 | ;; 573 | esac 574 | 575 | exit 0 576 | 577 | # Local Variables: 578 | # mode: shell-script 579 | # sh-indentation: 2 580 | # eval: (add-hook 'write-file-hooks 'time-stamp) 581 | # time-stamp-start: "scriptversion=" 582 | # time-stamp-format: "%:y-%02m-%02d.%02H" 583 | # time-stamp-end: "$" 584 | # End: 585 | -------------------------------------------------------------------------------- /scripts/install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install - install a program, script, or datafile 3 | 4 | scriptversion=2006-10-14.15 5 | 6 | # This originates from X11R5 (mit/util/scripts/install.sh), which was 7 | # later released in X11R6 (xc/config/util/install.sh) with the 8 | # following copyright and license. 9 | # 10 | # Copyright (C) 1994 X Consortium 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to 14 | # deal in the Software without restriction, including without limitation the 15 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | # sell copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in 20 | # all copies or substantial portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 | # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27 | # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | # 29 | # Except as contained in this notice, the name of the X Consortium shall not 30 | # be used in advertising or otherwise to promote the sale, use or other deal- 31 | # ings in this Software without prior written authorization from the X Consor- 32 | # tium. 33 | # 34 | # 35 | # FSF changes to this file are in the public domain. 36 | # 37 | # Calling this script install-sh is preferred over install.sh, to prevent 38 | # `make' implicit rules from creating a file called install from it 39 | # when there is no Makefile. 40 | # 41 | # This script is compatible with the BSD install script, but was written 42 | # from scratch. 43 | 44 | nl=' 45 | ' 46 | IFS=" "" $nl" 47 | 48 | # set DOITPROG to echo to test this script 49 | 50 | # Don't use :- since 4.3BSD and earlier shells don't like it. 51 | doit="${DOITPROG-}" 52 | if test -z "$doit"; then 53 | doit_exec=exec 54 | else 55 | doit_exec=$doit 56 | fi 57 | 58 | # Put in absolute file names if you don't have them in your path; 59 | # or use environment vars. 60 | 61 | mvprog="${MVPROG-mv}" 62 | cpprog="${CPPROG-cp}" 63 | chmodprog="${CHMODPROG-chmod}" 64 | chownprog="${CHOWNPROG-chown}" 65 | chgrpprog="${CHGRPPROG-chgrp}" 66 | stripprog="${STRIPPROG-strip}" 67 | rmprog="${RMPROG-rm}" 68 | mkdirprog="${MKDIRPROG-mkdir}" 69 | 70 | posix_glob= 71 | posix_mkdir= 72 | 73 | # Desired mode of installed file. 74 | mode=0755 75 | 76 | chmodcmd=$chmodprog 77 | chowncmd= 78 | chgrpcmd= 79 | stripcmd= 80 | rmcmd="$rmprog -f" 81 | mvcmd="$mvprog" 82 | src= 83 | dst= 84 | dir_arg= 85 | dstarg= 86 | no_target_directory= 87 | 88 | usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 89 | or: $0 [OPTION]... SRCFILES... DIRECTORY 90 | or: $0 [OPTION]... -t DIRECTORY SRCFILES... 91 | or: $0 [OPTION]... -d DIRECTORIES... 92 | 93 | In the 1st form, copy SRCFILE to DSTFILE. 94 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 95 | In the 4th, create DIRECTORIES. 96 | 97 | Options: 98 | -c (ignored) 99 | -d create directories instead of installing files. 100 | -g GROUP $chgrpprog installed files to GROUP. 101 | -m MODE $chmodprog installed files to MODE. 102 | -o USER $chownprog installed files to USER. 103 | -s $stripprog installed files. 104 | -t DIRECTORY install into DIRECTORY. 105 | -T report an error if DSTFILE is a directory. 106 | --help display this help and exit. 107 | --version display version info and exit. 108 | 109 | Environment variables override the default commands: 110 | CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 111 | " 112 | 113 | while test $# -ne 0; do 114 | case $1 in 115 | -c) shift 116 | continue;; 117 | 118 | -d) dir_arg=true 119 | shift 120 | continue;; 121 | 122 | -g) chgrpcmd="$chgrpprog $2" 123 | shift 124 | shift 125 | continue;; 126 | 127 | --help) echo "$usage"; exit $?;; 128 | 129 | -m) mode=$2 130 | shift 131 | shift 132 | case $mode in 133 | *' '* | *' '* | *' 134 | '* | *'*'* | *'?'* | *'['*) 135 | echo "$0: invalid mode: $mode" >&2 136 | exit 1;; 137 | esac 138 | continue;; 139 | 140 | -o) chowncmd="$chownprog $2" 141 | shift 142 | shift 143 | continue;; 144 | 145 | -s) stripcmd=$stripprog 146 | shift 147 | continue;; 148 | 149 | -t) dstarg=$2 150 | shift 151 | shift 152 | continue;; 153 | 154 | -T) no_target_directory=true 155 | shift 156 | continue;; 157 | 158 | --version) echo "$0 $scriptversion"; exit $?;; 159 | 160 | --) shift 161 | break;; 162 | 163 | -*) echo "$0: invalid option: $1" >&2 164 | exit 1;; 165 | 166 | *) break;; 167 | esac 168 | done 169 | 170 | if test $# -ne 0 && test -z "$dir_arg$dstarg"; then 171 | # When -d is used, all remaining arguments are directories to create. 172 | # When -t is used, the destination is already specified. 173 | # Otherwise, the last argument is the destination. Remove it from $@. 174 | for arg 175 | do 176 | if test -n "$dstarg"; then 177 | # $@ is not empty: it contains at least $arg. 178 | set fnord "$@" "$dstarg" 179 | shift # fnord 180 | fi 181 | shift # arg 182 | dstarg=$arg 183 | done 184 | fi 185 | 186 | if test $# -eq 0; then 187 | if test -z "$dir_arg"; then 188 | echo "$0: no input file specified." >&2 189 | exit 1 190 | fi 191 | # It's OK to call `install-sh -d' without argument. 192 | # This can happen when creating conditional directories. 193 | exit 0 194 | fi 195 | 196 | if test -z "$dir_arg"; then 197 | trap '(exit $?); exit' 1 2 13 15 198 | 199 | # Set umask so as not to create temps with too-generous modes. 200 | # However, 'strip' requires both read and write access to temps. 201 | case $mode in 202 | # Optimize common cases. 203 | *644) cp_umask=133;; 204 | *755) cp_umask=22;; 205 | 206 | *[0-7]) 207 | if test -z "$stripcmd"; then 208 | u_plus_rw= 209 | else 210 | u_plus_rw='% 200' 211 | fi 212 | cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 213 | *) 214 | if test -z "$stripcmd"; then 215 | u_plus_rw= 216 | else 217 | u_plus_rw=,u+rw 218 | fi 219 | cp_umask=$mode$u_plus_rw;; 220 | esac 221 | fi 222 | 223 | for src 224 | do 225 | # Protect names starting with `-'. 226 | case $src in 227 | -*) src=./$src ;; 228 | esac 229 | 230 | if test -n "$dir_arg"; then 231 | dst=$src 232 | dstdir=$dst 233 | test -d "$dstdir" 234 | dstdir_status=$? 235 | else 236 | 237 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 238 | # might cause directories to be created, which would be especially bad 239 | # if $src (and thus $dsttmp) contains '*'. 240 | if test ! -f "$src" && test ! -d "$src"; then 241 | echo "$0: $src does not exist." >&2 242 | exit 1 243 | fi 244 | 245 | if test -z "$dstarg"; then 246 | echo "$0: no destination specified." >&2 247 | exit 1 248 | fi 249 | 250 | dst=$dstarg 251 | # Protect names starting with `-'. 252 | case $dst in 253 | -*) dst=./$dst ;; 254 | esac 255 | 256 | # If destination is a directory, append the input filename; won't work 257 | # if double slashes aren't ignored. 258 | if test -d "$dst"; then 259 | if test -n "$no_target_directory"; then 260 | echo "$0: $dstarg: Is a directory" >&2 261 | exit 1 262 | fi 263 | dstdir=$dst 264 | dst=$dstdir/`basename "$src"` 265 | dstdir_status=0 266 | else 267 | # Prefer dirname, but fall back on a substitute if dirname fails. 268 | dstdir=` 269 | (dirname "$dst") 2>/dev/null || 270 | expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 271 | X"$dst" : 'X\(//\)[^/]' \| \ 272 | X"$dst" : 'X\(//\)$' \| \ 273 | X"$dst" : 'X\(/\)' \| . 2>/dev/null || 274 | echo X"$dst" | 275 | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 276 | s//\1/ 277 | q 278 | } 279 | /^X\(\/\/\)[^/].*/{ 280 | s//\1/ 281 | q 282 | } 283 | /^X\(\/\/\)$/{ 284 | s//\1/ 285 | q 286 | } 287 | /^X\(\/\).*/{ 288 | s//\1/ 289 | q 290 | } 291 | s/.*/./; q' 292 | ` 293 | 294 | test -d "$dstdir" 295 | dstdir_status=$? 296 | fi 297 | fi 298 | 299 | obsolete_mkdir_used=false 300 | 301 | if test $dstdir_status != 0; then 302 | case $posix_mkdir in 303 | '') 304 | # Create intermediate dirs using mode 755 as modified by the umask. 305 | # This is like FreeBSD 'install' as of 1997-10-28. 306 | umask=`umask` 307 | case $stripcmd.$umask in 308 | # Optimize common cases. 309 | *[2367][2367]) mkdir_umask=$umask;; 310 | .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 311 | 312 | *[0-7]) 313 | mkdir_umask=`expr $umask + 22 \ 314 | - $umask % 100 % 40 + $umask % 20 \ 315 | - $umask % 10 % 4 + $umask % 2 316 | `;; 317 | *) mkdir_umask=$umask,go-w;; 318 | esac 319 | 320 | # With -d, create the new directory with the user-specified mode. 321 | # Otherwise, rely on $mkdir_umask. 322 | if test -n "$dir_arg"; then 323 | mkdir_mode=-m$mode 324 | else 325 | mkdir_mode= 326 | fi 327 | 328 | posix_mkdir=false 329 | case $umask in 330 | *[123567][0-7][0-7]) 331 | # POSIX mkdir -p sets u+wx bits regardless of umask, which 332 | # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 333 | ;; 334 | *) 335 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 336 | trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 337 | 338 | if (umask $mkdir_umask && 339 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 340 | then 341 | if test -z "$dir_arg" || { 342 | # Check for POSIX incompatibilities with -m. 343 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 344 | # other-writeable bit of parent directory when it shouldn't. 345 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 346 | ls_ld_tmpdir=`ls -ld "$tmpdir"` 347 | case $ls_ld_tmpdir in 348 | d????-?r-*) different_mode=700;; 349 | d????-?--*) different_mode=755;; 350 | *) false;; 351 | esac && 352 | $mkdirprog -m$different_mode -p -- "$tmpdir" && { 353 | ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 354 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 355 | } 356 | } 357 | then posix_mkdir=: 358 | fi 359 | rmdir "$tmpdir/d" "$tmpdir" 360 | else 361 | # Remove any dirs left behind by ancient mkdir implementations. 362 | rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 363 | fi 364 | trap '' 0;; 365 | esac;; 366 | esac 367 | 368 | if 369 | $posix_mkdir && ( 370 | umask $mkdir_umask && 371 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 372 | ) 373 | then : 374 | else 375 | 376 | # The umask is ridiculous, or mkdir does not conform to POSIX, 377 | # or it failed possibly due to a race condition. Create the 378 | # directory the slow way, step by step, checking for races as we go. 379 | 380 | case $dstdir in 381 | /*) prefix=/ ;; 382 | -*) prefix=./ ;; 383 | *) prefix= ;; 384 | esac 385 | 386 | case $posix_glob in 387 | '') 388 | if (set -f) 2>/dev/null; then 389 | posix_glob=true 390 | else 391 | posix_glob=false 392 | fi ;; 393 | esac 394 | 395 | oIFS=$IFS 396 | IFS=/ 397 | $posix_glob && set -f 398 | set fnord $dstdir 399 | shift 400 | $posix_glob && set +f 401 | IFS=$oIFS 402 | 403 | prefixes= 404 | 405 | for d 406 | do 407 | test -z "$d" && continue 408 | 409 | prefix=$prefix$d 410 | if test -d "$prefix"; then 411 | prefixes= 412 | else 413 | if $posix_mkdir; then 414 | (umask=$mkdir_umask && 415 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 416 | # Don't fail if two instances are running concurrently. 417 | test -d "$prefix" || exit 1 418 | else 419 | case $prefix in 420 | *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 421 | *) qprefix=$prefix;; 422 | esac 423 | prefixes="$prefixes '$qprefix'" 424 | fi 425 | fi 426 | prefix=$prefix/ 427 | done 428 | 429 | if test -n "$prefixes"; then 430 | # Don't fail if two instances are running concurrently. 431 | (umask $mkdir_umask && 432 | eval "\$doit_exec \$mkdirprog $prefixes") || 433 | test -d "$dstdir" || exit 1 434 | obsolete_mkdir_used=true 435 | fi 436 | fi 437 | fi 438 | 439 | if test -n "$dir_arg"; then 440 | { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 441 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 442 | { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 443 | test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 444 | else 445 | 446 | # Make a couple of temp file names in the proper directory. 447 | dsttmp=$dstdir/_inst.$$_ 448 | rmtmp=$dstdir/_rm.$$_ 449 | 450 | # Trap to clean up those temp files at exit. 451 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 452 | 453 | # Copy the file name to the temp name. 454 | (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 455 | 456 | # and set any options; do chmod last to preserve setuid bits. 457 | # 458 | # If any of these fail, we abort the whole thing. If we want to 459 | # ignore errors from any of these, just make sure not to ignore 460 | # errors from the above "$doit $cpprog $src $dsttmp" command. 461 | # 462 | { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 463 | && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 464 | && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 465 | && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 466 | 467 | # Now rename the file to the real destination. 468 | { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \ 469 | || { 470 | # The rename failed, perhaps because mv can't rename something else 471 | # to itself, or perhaps because mv is so ancient that it does not 472 | # support -f. 473 | 474 | # Now remove or move aside any old file at destination location. 475 | # We try this two ways since rm can't unlink itself on some 476 | # systems and the destination file might be busy for other 477 | # reasons. In this case, the final cleanup might fail but the new 478 | # file should still install successfully. 479 | { 480 | if test -f "$dst"; then 481 | $doit $rmcmd -f "$dst" 2>/dev/null \ 482 | || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \ 483 | && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\ 484 | || { 485 | echo "$0: cannot unlink or rename $dst" >&2 486 | (exit 1); exit 1 487 | } 488 | else 489 | : 490 | fi 491 | } && 492 | 493 | # Now rename the file to the real destination. 494 | $doit $mvcmd "$dsttmp" "$dst" 495 | } 496 | } || exit 1 497 | 498 | trap '' 0 499 | fi 500 | done 501 | 502 | # Local variables: 503 | # eval: (add-hook 'write-file-hooks 'time-stamp) 504 | # time-stamp-start: "scriptversion=" 505 | # time-stamp-format: "%:y-%02m-%02d.%02H" 506 | # time-stamp-end: "$" 507 | # End: 508 | -------------------------------------------------------------------------------- /scripts/lean.m4: -------------------------------------------------------------------------------- 1 | # autotools lean macros 2 | # hg 2012-08-29 cf2aa779c26c 3 | 4 | # Copyright (c) 2012 Gregor Richards 5 | # 6 | # Permission to use, copy, modify, and/or distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD 11 | # TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 12 | # FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, 13 | # OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 14 | # USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 | # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 16 | # OF THIS SOFTWARE. 17 | 18 | # These macros make auto* tests faster by removing some of autoconf's most 19 | # absurd defaults. The basic principle is to not check for things that have no 20 | # alternatives. That is, don't perform a test if it's either going to pass and 21 | # affect nothing, or fail and just prevent you from building. These tests 22 | # provide very little real value since modern systems that they fail on are few 23 | # and far between. 24 | 25 | 26 | # automake's sanity checks provide nothing useful, since all they can do is 27 | # fail, sometimes spuriously, and prevent builds which may otherwise have 28 | # succeeded. 29 | AC_DEFUN([AM_SANITY_CHECK], [ ]) 30 | 31 | 32 | # Checking for C89 compliance nowadays is just plain silly. 33 | AC_DEFUN([_AC_PROG_CC_C89], [ ]) 34 | 35 | 36 | # For the same reason, checking for C standard headers is usually stupid. 37 | # However, we simply avoid checking for them in the most ridiculous cases. 38 | m4_define([ACX_PRELEAN_AC_CHECK_HEADER], m4_defn([AC_CHECK_HEADER])) 39 | AC_DEFUN([AC_CHECK_HEADER], [ 40 | m4_case([$4], 41 | [], [ACX_PRELEAN_AC_CHECK_HEADER([$1], [$2], [$3], [ ])], 42 | [m4_indir([ACX_PRELEAN_AC_CHECK_HEADER], $@)]) 43 | ]) 44 | m4_define([_AC_HEADERS_EXPANSION], [ 45 | m4_divert_text([DEFAULTS], [ac_header_list=]) 46 | AC_CHECK_HEADERS([$ac_header_list], [], [], [ ]) 47 | m4_define([_AC_HEADERS_EXPANSION], []) 48 | ]) 49 | m4_define([ACX_PRELEAN_AC_CHECK_SIZEOF], m4_defn([AC_CHECK_SIZEOF])) 50 | AC_DEFUN([AC_CHECK_SIZEOF], [ 51 | m4_case([$3], 52 | [], [ACX_PRELEAN_AC_CHECK_SIZEOF([$1], [], [ ])], 53 | [m4_indir([ACX_PRELEAN_AC_CHECK_SIZEOF])], $@)]) 54 | 55 | 56 | # And add warnings for known-nasty builtin checks 57 | m4_define([ACX_UNLEAN_AC_FUNC_MMAP], m4_defn([AC_FUNC_MMAP])) 58 | AC_DEFUN([AC_FUNC_MMAP], [ 59 | AC_DIAGNOSE([syntax], [$0: AC_FUNC_MMAP does not work in cross environments and incurs high costs. Check for mmap directly if you aren't concerned about enormously-broken implementations. Use ACX_LEAN_AC_FUNC_MMAP to silence this warning.]) 60 | ACX_LEAN_AC_FUNC_MMAP 61 | ]) 62 | 63 | 64 | # POSIX says that make sets $(MAKE). That's good enough for me. 65 | AC_DEFUN([AC_PROG_MAKE_SET], [ 66 | ac_cv_prog_make_make_set=yes 67 | SET_MAKE= 68 | AC_SUBST([SET_MAKE]) 69 | ]) 70 | 71 | 72 | # configure will simply fail, often spuriously, if you don't tell it that 73 | # you're cross compiling, so there's very little reason to explicitly check. 74 | AC_DEFUN([_AC_COMPILER_EXEEXT_CROSS], [ 75 | if test "$cross_compiling" = "maybe"; then 76 | cross_compiling=yes 77 | fi 78 | ]) 79 | 80 | 81 | # Allow the default GCC-and-compatible CFLAGS to be changed 82 | GCC_DEFAULT_CFLAGS="-g -O2" 83 | 84 | 85 | # The builtin -g test is simplified by avoiding rechecks for GCC (of course GCC 86 | # supports -g) 87 | m4_define([ACX_PRELEAN__AC_PROG_CC_G], m4_defn([_AC_PROG_CC_G])) 88 | m4_define([_AC_PROG_CC_G], [ 89 | if test "$GCC" = "yes"; then 90 | acx_lean_CFLAGS_set=${CFLAGS+set} 91 | ac_cv_prog_cc_g=yes 92 | if test "$acx_lean_CFLAGS_set" != "set"; then 93 | CFLAGS="$GCC_DEFAULT_CFLAGS" 94 | fi 95 | else 96 | ACX_PRELEAN__AC_PROG_CC_G 97 | fi 98 | ]) 99 | 100 | 101 | # Option to force caching 102 | AC_DEFUN([ACX_LEAN_FORCE_CACHE], [ 103 | m4_define([acx_lean_forced_cache], [yes]) 104 | if test "$cache_file" = "/dev/null"; then 105 | cache_file=config.cache 106 | fi 107 | ]) 108 | 109 | 110 | # Force the use of a cache file if we use subdirectories, as otherwise we 111 | # retest things in the subdirs. 112 | m4_define([ACX_PRELEAN_AC_CONFIG_SUBDIRS], m4_defn([AC_CONFIG_SUBDIRS])) 113 | AC_DEFUN([AC_CONFIG_SUBDIRS], [ 114 | m4_ifdef([acx_lean_forced_cache], [], [ 115 | AC_DIAGNOSE([syntax], [$0: Use ACX_LEAN_FORCE_CACHE after initialization to avoid extra costs with configure subdirs.]) 116 | ]) 117 | ACX_PRELEAN_AC_CONFIG_SUBDIRS($1) 118 | ]) 119 | -------------------------------------------------------------------------------- /scripts/missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | exit 0 3 | # Common stub for a few missing GNU programs while installing. 4 | 5 | scriptversion=2006-05-10.23 6 | 7 | # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 8 | # Free Software Foundation, Inc. 9 | # Originally by Fran,cois Pinard , 1996. 10 | 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2, or (at your option) 14 | # any later version. 15 | 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 24 | # 02110-1301, USA. 25 | 26 | # As a special exception to the GNU General Public License, if you 27 | # distribute this file as part of a program that contains a 28 | # configuration script generated by Autoconf, you may include it under 29 | # the same distribution terms that you use for the rest of that program. 30 | 31 | if test $# -eq 0; then 32 | echo 1>&2 "Try \`$0 --help' for more information" 33 | exit 1 34 | fi 35 | 36 | run=: 37 | sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' 38 | sed_minuso='s/.* -o \([^ ]*\).*/\1/p' 39 | 40 | # In the cases where this matters, `missing' is being run in the 41 | # srcdir already. 42 | if test -f configure.ac; then 43 | configure_ac=configure.ac 44 | else 45 | configure_ac=configure.in 46 | fi 47 | 48 | msg="missing on your system" 49 | 50 | case $1 in 51 | --run) 52 | # Try to run requested program, and just exit if it succeeds. 53 | run= 54 | shift 55 | "$@" && exit 0 56 | # Exit code 63 means version mismatch. This often happens 57 | # when the user try to use an ancient version of a tool on 58 | # a file that requires a minimum version. In this case we 59 | # we should proceed has if the program had been absent, or 60 | # if --run hadn't been passed. 61 | if test $? = 63; then 62 | run=: 63 | msg="probably too old" 64 | fi 65 | ;; 66 | 67 | -h|--h|--he|--hel|--help) 68 | echo "\ 69 | $0 [OPTION]... PROGRAM [ARGUMENT]... 70 | 71 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an 72 | error status if there is no known handling for PROGRAM. 73 | 74 | Options: 75 | -h, --help display this help and exit 76 | -v, --version output version information and exit 77 | --run try to run the given command, and emulate it if it fails 78 | 79 | Supported PROGRAM values: 80 | aclocal touch file \`aclocal.m4' 81 | autoconf touch file \`configure' 82 | autoheader touch file \`config.h.in' 83 | autom4te touch the output file, or create a stub one 84 | automake touch all \`Makefile.in' files 85 | bison create \`y.tab.[ch]', if possible, from existing .[ch] 86 | flex create \`lex.yy.c', if possible, from existing .c 87 | help2man touch the output file 88 | lex create \`lex.yy.c', if possible, from existing .c 89 | makeinfo touch the output file 90 | tar try tar, gnutar, gtar, then tar without non-portable flags 91 | yacc create \`y.tab.[ch]', if possible, from existing .[ch] 92 | 93 | Send bug reports to ." 94 | exit $? 95 | ;; 96 | 97 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 98 | echo "missing $scriptversion (GNU Automake)" 99 | exit $? 100 | ;; 101 | 102 | -*) 103 | echo 1>&2 "$0: Unknown \`$1' option" 104 | echo 1>&2 "Try \`$0 --help' for more information" 105 | exit 1 106 | ;; 107 | 108 | esac 109 | 110 | # Now exit if we have it, but it failed. Also exit now if we 111 | # don't have it and --version was passed (most likely to detect 112 | # the program). 113 | case $1 in 114 | lex|yacc) 115 | # Not GNU programs, they don't have --version. 116 | ;; 117 | 118 | tar) 119 | if test -n "$run"; then 120 | echo 1>&2 "ERROR: \`tar' requires --run" 121 | exit 1 122 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 123 | exit 1 124 | fi 125 | ;; 126 | 127 | *) 128 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 129 | # We have it, but it failed. 130 | exit 1 131 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 132 | # Could not run --version or --help. This is probably someone 133 | # running `$TOOL --version' or `$TOOL --help' to check whether 134 | # $TOOL exists and not knowing $TOOL uses missing. 135 | exit 1 136 | fi 137 | ;; 138 | esac 139 | 140 | # If it does not exist, or fails to run (possibly an outdated version), 141 | # try to emulate it. 142 | case $1 in 143 | aclocal*) 144 | echo 1>&2 "\ 145 | WARNING: \`$1' is $msg. You should only need it if 146 | you modified \`acinclude.m4' or \`${configure_ac}'. You might want 147 | to install the \`Automake' and \`Perl' packages. Grab them from 148 | any GNU archive site." 149 | touch aclocal.m4 150 | ;; 151 | 152 | autoconf) 153 | echo 1>&2 "\ 154 | WARNING: \`$1' is $msg. You should only need it if 155 | you modified \`${configure_ac}'. You might want to install the 156 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU 157 | archive site." 158 | touch configure 159 | ;; 160 | 161 | autoheader) 162 | echo 1>&2 "\ 163 | WARNING: \`$1' is $msg. You should only need it if 164 | you modified \`acconfig.h' or \`${configure_ac}'. You might want 165 | to install the \`Autoconf' and \`GNU m4' packages. Grab them 166 | from any GNU archive site." 167 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` 168 | test -z "$files" && files="config.h" 169 | touch_files= 170 | for f in $files; do 171 | case $f in 172 | *:*) touch_files="$touch_files "`echo "$f" | 173 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; 174 | *) touch_files="$touch_files $f.in";; 175 | esac 176 | done 177 | touch $touch_files 178 | ;; 179 | 180 | automake*) 181 | echo 1>&2 "\ 182 | WARNING: \`$1' is $msg. You should only need it if 183 | you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. 184 | You might want to install the \`Automake' and \`Perl' packages. 185 | Grab them from any GNU archive site." 186 | find . -type f -name Makefile.am -print | 187 | sed 's/\.am$/.in/' | 188 | while read f; do touch "$f"; done 189 | ;; 190 | 191 | autom4te) 192 | echo 1>&2 "\ 193 | WARNING: \`$1' is needed, but is $msg. 194 | You might have modified some files without having the 195 | proper tools for further handling them. 196 | You can get \`$1' as part of \`Autoconf' from any GNU 197 | archive site." 198 | 199 | file=`echo "$*" | sed -n "$sed_output"` 200 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 201 | if test -f "$file"; then 202 | touch $file 203 | else 204 | test -z "$file" || exec >$file 205 | echo "#! /bin/sh" 206 | echo "# Created by GNU Automake missing as a replacement of" 207 | echo "# $ $@" 208 | echo "exit 0" 209 | chmod +x $file 210 | exit 1 211 | fi 212 | ;; 213 | 214 | bison|yacc) 215 | echo 1>&2 "\ 216 | WARNING: \`$1' $msg. You should only need it if 217 | you modified a \`.y' file. You may need the \`Bison' package 218 | in order for those modifications to take effect. You can get 219 | \`Bison' from any GNU archive site." 220 | rm -f y.tab.c y.tab.h 221 | if test $# -ne 1; then 222 | eval LASTARG="\${$#}" 223 | case $LASTARG in 224 | *.y) 225 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` 226 | if test -f "$SRCFILE"; then 227 | cp "$SRCFILE" y.tab.c 228 | fi 229 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` 230 | if test -f "$SRCFILE"; then 231 | cp "$SRCFILE" y.tab.h 232 | fi 233 | ;; 234 | esac 235 | fi 236 | if test ! -f y.tab.h; then 237 | echo >y.tab.h 238 | fi 239 | if test ! -f y.tab.c; then 240 | echo 'main() { return 0; }' >y.tab.c 241 | fi 242 | ;; 243 | 244 | lex|flex) 245 | echo 1>&2 "\ 246 | WARNING: \`$1' is $msg. You should only need it if 247 | you modified a \`.l' file. You may need the \`Flex' package 248 | in order for those modifications to take effect. You can get 249 | \`Flex' from any GNU archive site." 250 | rm -f lex.yy.c 251 | if test $# -ne 1; then 252 | eval LASTARG="\${$#}" 253 | case $LASTARG in 254 | *.l) 255 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` 256 | if test -f "$SRCFILE"; then 257 | cp "$SRCFILE" lex.yy.c 258 | fi 259 | ;; 260 | esac 261 | fi 262 | if test ! -f lex.yy.c; then 263 | echo 'main() { return 0; }' >lex.yy.c 264 | fi 265 | ;; 266 | 267 | help2man) 268 | echo 1>&2 "\ 269 | WARNING: \`$1' is $msg. You should only need it if 270 | you modified a dependency of a manual page. You may need the 271 | \`Help2man' package in order for those modifications to take 272 | effect. You can get \`Help2man' from any GNU archive site." 273 | 274 | file=`echo "$*" | sed -n "$sed_output"` 275 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 276 | if test -f "$file"; then 277 | touch $file 278 | else 279 | test -z "$file" || exec >$file 280 | echo ".ab help2man is required to generate this page" 281 | exit 1 282 | fi 283 | ;; 284 | 285 | makeinfo) 286 | echo 1>&2 "\ 287 | WARNING: \`$1' is $msg. You should only need it if 288 | you modified a \`.texi' or \`.texinfo' file, or any other file 289 | indirectly affecting the aspect of the manual. The spurious 290 | call might also be the consequence of using a buggy \`make' (AIX, 291 | DU, IRIX). You might want to install the \`Texinfo' package or 292 | the \`GNU make' package. Grab either from any GNU archive site." 293 | # The file to touch is that specified with -o ... 294 | file=`echo "$*" | sed -n "$sed_output"` 295 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 296 | if test -z "$file"; then 297 | # ... or it is the one specified with @setfilename ... 298 | infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` 299 | file=`sed -n ' 300 | /^@setfilename/{ 301 | s/.* \([^ ]*\) *$/\1/ 302 | p 303 | q 304 | }' $infile` 305 | # ... or it is derived from the source name (dir/f.texi becomes f.info) 306 | test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info 307 | fi 308 | # If the file does not exist, the user really needs makeinfo; 309 | # let's fail without touching anything. 310 | test -f $file || exit 1 311 | touch $file 312 | ;; 313 | 314 | tar) 315 | shift 316 | 317 | # We have already tried tar in the generic part. 318 | # Look for gnutar/gtar before invocation to avoid ugly error 319 | # messages. 320 | if (gnutar --version > /dev/null 2>&1); then 321 | gnutar "$@" && exit 0 322 | fi 323 | if (gtar --version > /dev/null 2>&1); then 324 | gtar "$@" && exit 0 325 | fi 326 | firstarg="$1" 327 | if shift; then 328 | case $firstarg in 329 | *o*) 330 | firstarg=`echo "$firstarg" | sed s/o//` 331 | tar "$firstarg" "$@" && exit 0 332 | ;; 333 | esac 334 | case $firstarg in 335 | *h*) 336 | firstarg=`echo "$firstarg" | sed s/h//` 337 | tar "$firstarg" "$@" && exit 0 338 | ;; 339 | esac 340 | fi 341 | 342 | echo 1>&2 "\ 343 | WARNING: I can't seem to be able to run \`tar' with the given arguments. 344 | You may want to install GNU tar or Free paxutils, or check the 345 | command line arguments." 346 | exit 1 347 | ;; 348 | 349 | *) 350 | echo 1>&2 "\ 351 | WARNING: \`$1' is needed, and is $msg. 352 | You might have modified some files without having the 353 | proper tools for further handling them. Check the \`README' file, 354 | it often tells you about the needed prerequisites for installing 355 | this package. You may also peek at any GNU archive site, in case 356 | some other package would contain this missing \`$1' program." 357 | exit 1 358 | ;; 359 | esac 360 | 361 | exit 0 362 | 363 | # Local variables: 364 | # eval: (add-hook 'write-file-hooks 'time-stamp) 365 | # time-stamp-start: "scriptversion=" 366 | # time-stamp-format: "%:y-%02m-%02d.%02H" 367 | # time-stamp-end: "$" 368 | # End: 369 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = gelfload-@GELFLOAD_ARCH@ gelfload-ld-@GELFLOAD_ARCH@ 2 | noinst_DATA = gelfload$(EXEEXT) 3 | lib_LIBRARIES = libgelfload.a 4 | 5 | gelfload_@GELFLOAD_ARCH@_SOURCES = main.c whereami.c 6 | gelfload_@GELFLOAD_ARCH@_DEPENDENCIES = libgelfload.a 7 | gelfload_@GELFLOAD_ARCH@_LDADD = libgelfload.a 8 | 9 | if HAVE_LIBDL 10 | gelfload_@GELFLOAD_ARCH@_LDADD += -ldl 11 | endif 12 | 13 | gelfload_ld_@GELFLOAD_ARCH@_SOURCES = elfload-ld.c whereami.c 14 | if HAVE_STATIC 15 | gelfload_ld_@GELFLOAD_ARCH@_LDFLAGS = -static 16 | endif 17 | 18 | libgelfload_a_SOURCES = bbuffer.c elfload.c dlfcn.c 19 | 20 | gelfload$(EXEEXT): gelfload-@GELFLOAD_ARCH@$(EXEEXT) 21 | -rm -f gelfload$(EXEEXT) 22 | $(LN_S) gelfload-@GELFLOAD_ARCH@$(EXEEXT) gelfload$(EXEEXT) 23 | 24 | install-exec-hook: 25 | cd $(DESTDIR)$(bindir) && \ 26 | rm -f gelfload$(EXEEXT) && \ 27 | $(LN_S) gelfload-@GELFLOAD_ARCH@$(EXEEXT) gelfload$(EXEEXT) 28 | -------------------------------------------------------------------------------- /src/bbuffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../config.h" 6 | 7 | #include "bbuffer.h" 8 | 9 | #if defined(HAVE_MMAP) 10 | #include 11 | 12 | /* mmap-based is the easiest */ 13 | void *bbuffer(void *loc, size_t sz) { 14 | void *ret; 15 | int page = getpagesize(); 16 | 17 | /* switch on fixed-ness */ 18 | if (loc) { 19 | /* make sure it's on a page boundary */ 20 | void *wantloc = loc; 21 | ssize_t offset; 22 | offset = (ssize_t) loc % page; 23 | if (offset) { 24 | sz += offset; 25 | loc -= offset; 26 | } 27 | 28 | ret = mmap(loc, sz, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON|MAP_FIXED, 29 | -1, 0); 30 | if (ret == loc) ret = wantloc; 31 | } else { 32 | ret = mmap(NULL, sz, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 33 | -1, 0); 34 | } 35 | 36 | if (ret == (void *) -1) { 37 | perror("mmap"); 38 | exit(1); 39 | } 40 | 41 | return ret; 42 | } 43 | 44 | #elif defined(__WIN32) 45 | #ifndef WIN32_LEAN_AND_MEAN 46 | #define WIN32_LEAN_AND_MEAN 47 | #endif 48 | #include 49 | 50 | void *bbuffer(void *loc, size_t sz) 51 | { 52 | /* shockingly, Windows makes this far more difficult than it needs to be */ 53 | SYSTEM_INFO si; 54 | MEMORY_BASIC_INFORMATION mbi; 55 | ssize_t agrn, offset, szoffset; 56 | void *q, *ret; 57 | 58 | if (loc) { 59 | /* the complicated case */ 60 | 61 | /* get the allocation granularity */ 62 | GetSystemInfo(&si); 63 | agrn = si.dwAllocationGranularity; 64 | 65 | /* make sure it's on the allocation granularity */ 66 | offset = (ssize_t) loc % agrn; 67 | if (offset) { 68 | sz += offset; 69 | loc -= offset; 70 | } 71 | 72 | /* then make sure sz is also aligned */ 73 | szoffset = sz % agrn; 74 | if (szoffset) { 75 | sz += (agrn - szoffset); 76 | } 77 | 78 | /* free everything */ 79 | for (q = loc; q < loc + sz; q += agrn) { 80 | if (VirtualQuery(q, &mbi, agrn) >= sizeof(mbi)) { 81 | if (mbi.State != MEM_FREE) { 82 | /* get rid of it */ 83 | if (mbi.Type & MEM_IMAGE) 84 | UnmapViewOfFile(mbi.AllocationBase); 85 | VirtualFree(mbi.AllocationBase, 0, MEM_RELEASE); 86 | } 87 | } 88 | } 89 | 90 | /* finally, allocate */ 91 | ret = VirtualAlloc(loc, sz, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); 92 | if (ret == NULL) { 93 | fprintf(stderr, "VirtualAlloc failed with error %d\n", GetLastError()); 94 | exit(1); 95 | } 96 | 97 | return ret + offset; 98 | 99 | } else { 100 | ret = VirtualAlloc(NULL, sz, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); 101 | if (ret == NULL) { 102 | fprintf(stderr, "VirtualAlloc failed with error %d\n", GetLastError()); 103 | exit(1); 104 | } 105 | 106 | return ret; 107 | 108 | } 109 | } 110 | 111 | #else 112 | 113 | void *bbuffer(void *loc, size_t sz) 114 | { 115 | /* worst case scenario, just malloc */ 116 | void *ret = malloc(sz); 117 | if (ret == NULL) { 118 | perror("malloc"); 119 | exit(1); 120 | } 121 | return ret; 122 | } 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /src/bbuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef BBUFFER_H 2 | #define BBUFER_H 3 | 4 | /* Get a r/w/x binary buffer, at the given location if provided */ 5 | void *bbuffer(void *loc, size_t sz); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /src/dlfcn.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "elfload.h" 4 | #include "elfload_dlfcn.h" 5 | 6 | char *elfload_dlinstdir = NULL; 7 | char *dlLastError = NULL; 8 | 9 | void *elfload_dlopen(const char *filename, int flag) 10 | { 11 | /* pretty simple, just load based on the file name */ 12 | struct ELF_File *f = loadELF(filename, elfload_dlinstdir, 0); 13 | 14 | if (f == NULL) { 15 | dlLastError = "Could not find or load file."; 16 | } 17 | 18 | return (void *) f; 19 | } 20 | 21 | char *elfload_dlerror(void) { return dlLastError; } 22 | 23 | void *elfload_dlsym(void *handle, const char *symbol) 24 | { 25 | void *sym = findELFSymbol(symbol, (struct ELF_File *) handle, -1, -1, NULL); 26 | 27 | if (sym == NULL) { 28 | dlLastError = "Symbol undefined."; 29 | } 30 | 31 | return sym; 32 | } 33 | 34 | int elfload_dlclose(void *handle) {return 0;} 35 | 36 | 37 | void *elfload_dl(const char *fname) 38 | { 39 | if (strcmp(fname, "dlopen") == 0) { 40 | return (void *) elfload_dlopen; 41 | 42 | } else if (strcmp(fname, "dlerror") == 0) { 43 | return (void *) elfload_dlerror; 44 | 45 | } else if (strcmp(fname, "dlsym") == 0) { 46 | return (void *) elfload_dlsym; 47 | 48 | } else if (strcmp(fname, "dlclose") == 0) { 49 | return (void *) elfload_dlclose; 50 | 51 | } 52 | 53 | return NULL; 54 | } 55 | -------------------------------------------------------------------------------- /src/elfload-ld.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../config.h" 6 | #include "whereami.h" 7 | 8 | int main(int argc, char **argv) 9 | { 10 | char **newargs; 11 | 12 | /* form our new arguments */ 13 | newargs = alloca((argc + 2) * sizeof(char*)); 14 | memcpy(newargs + 1, argv, (argc + 1) * sizeof(char*)); 15 | newargs[0] = PREFIX "/bin/gelfload"; 16 | 17 | /* make the program name absolute */ 18 | if (argv[0][0] != '/') { 19 | char *dir, *fil; 20 | if (whereAmI(argv[0], &dir, &fil)) { 21 | char *newargv1 = alloca(strlen(dir) + strlen(fil) + 2); 22 | sprintf(newargv1, "%s/%s", dir, fil); 23 | newargs[1] = newargv1; 24 | } 25 | } 26 | 27 | /* then call */ 28 | execv(newargs[0], newargs); 29 | fprintf(stderr, "Failed to call %s\n", newargs[0]); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /src/elfload.c: -------------------------------------------------------------------------------- 1 | #ifndef _GNU_SOURCE /* for RTLD_DEFAULT */ 2 | #define _GNU_SOURCE 1 3 | #endif 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "bbuffer.h" 14 | 15 | #include "../config.h" 16 | 17 | #ifdef HAVE_MMAP 18 | #include 19 | #endif 20 | 21 | #ifdef HAVE_DLFCN_H 22 | #include 23 | #endif 24 | 25 | #ifdef __WIN32 26 | #ifndef WIN32_LEAN_AND_MEAN 27 | #define WIN32_LEAN_AND_MEAN 28 | #endif 29 | #include 30 | #endif 31 | 32 | #include "elfload.h" 33 | #include "elfload_dlfcn.h" 34 | 35 | /* An array of files currently in the process of loading */ 36 | #define MAX_ELF_FILES 255 37 | struct ELF_File elfFiles[MAX_ELF_FILES]; 38 | int elfFileCount = 0; 39 | 40 | /* The function to actually load ELF files into memory */ 41 | struct ELF_File *loadELF(const char *nm, const char *instdir, int maybe) 42 | { 43 | int i, fileNo, phdri; 44 | struct ELF_File *f; 45 | void *curphdrl; 46 | ElfNative_Phdr *curphdr; 47 | ElfNative_Dyn *curdyn; 48 | 49 | /* first, make sure it's not already loaded or loading */ 50 | for (i = 0; i < elfFileCount; i++) { 51 | if (strcmp(elfFiles[i].nm, nm) == 0) return &(elfFiles[i]); 52 | } 53 | 54 | /* now start preparing to load it */ 55 | fileNo = elfFileCount; 56 | f = &(elfFiles[fileNo]); 57 | memset(f, 0, sizeof(struct ELF_File)); 58 | elfFileCount++; 59 | f->nm = strdup(nm); 60 | 61 | /* if this is a host library, circumvent all the ELF stuff and go straight for the host */ 62 | if (strncmp(nm, "libhost_", 8) == 0) { 63 | f->hostlib = HOSTLIB_HOST; 64 | #if defined(HAVE_DLFCN_H) 65 | if (strcmp(nm, "libhost_.so") == 0) { 66 | /* the entire host */ 67 | #ifdef RTLD_DEFAULT 68 | f->prog = RTLD_DEFAULT; 69 | #else 70 | f->prog = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL); 71 | #endif 72 | } else { 73 | f->prog = dlopen(nm + 8, RTLD_NOW|RTLD_GLOBAL); 74 | 75 | if (f->prog == NULL) { 76 | /* try with an explicit path */ 77 | char *fullpath; 78 | fullpath = malloc(strlen(elfload_dlinstdir) + strlen(nm) + 1); 79 | if (fullpath == NULL) { 80 | perror("malloc"); 81 | exit(1); 82 | } 83 | sprintf(fullpath, "%s/../lib/%s", elfload_dlinstdir, nm + 8); 84 | f->prog = dlopen(fullpath, RTLD_NOW|RTLD_GLOBAL); 85 | free(fullpath); 86 | } 87 | 88 | if (f->prog == NULL) { 89 | fprintf(stderr, "Could not resolve host library %s: %s.\n", nm + 8, dlerror()); 90 | exit(1); 91 | } 92 | } 93 | #elif defined(__WIN32) 94 | if (strcmp(nm, "libhost_.so") == 0) { 95 | f->prog = LoadLibrary("msvcrt.dll"); 96 | } else { 97 | f->prog = LoadLibrary(nm + 8); 98 | } 99 | if (f->prog == NULL) { 100 | fprintf(stderr, "Could not resolve host library %s.\n", nm + 8); 101 | exit(1); 102 | } 103 | #else 104 | fprintf(stderr, "This version of elfload is not capable of loading the host library %s.\n", 105 | nm + 8); 106 | exit(1); 107 | #endif 108 | return f; 109 | 110 | } else if (strncmp(nm, "libloader_", 10) == 0) { 111 | /* must be provided by the loader. Only dl.0 is provided right now */ 112 | if (strcmp(nm, "libloader_dl.0") == 0) { 113 | f->hostlib = HOSTLIB_DL; 114 | 115 | } else { 116 | fprintf(stderr, "Loader lib %s unsupported.\n", nm); 117 | exit(1); 118 | 119 | } 120 | 121 | return f; 122 | } 123 | 124 | readFile(nm, instdir, f); 125 | 126 | /* make sure it's an ELF file */ 127 | f->ehdr = (ElfNative_Ehdr *) f->prog; 128 | if (memcmp(f->ehdr->e_ident, ELFMAG, SELFMAG) != 0) { 129 | if (!maybe) { 130 | fprintf(stderr, "%s does not appear to be an ELF file.\n", nm); 131 | exit(1); 132 | } else { 133 | return NULL; 134 | } 135 | } 136 | 137 | /* only native-bit supported for the moment */ 138 | if ((SIZEOF_VOID_P == 4 && f->ehdr->e_ident[EI_CLASS] != ELFCLASS32) || 139 | (SIZEOF_VOID_P == 8 && f->ehdr->e_ident[EI_CLASS] != ELFCLASS64)) { 140 | if (!maybe) { 141 | fprintf(stderr, "%s is not a %d-bit ELF file.\n", nm, SIZEOF_VOID_P * 8); 142 | exit(1); 143 | } else { 144 | return NULL; 145 | } 146 | } 147 | 148 | /* FIXME: check endianness */ 149 | 150 | /* must be an executable or .so to be loaded */ 151 | if (f->ehdr->e_type != ET_EXEC && 152 | f->ehdr->e_type != ET_DYN) { 153 | if (!maybe) { 154 | fprintf(stderr, "%s is not an executable or shared object file.\n", nm); 155 | exit(1); 156 | } else { 157 | return NULL; 158 | } 159 | } 160 | 161 | /* now go through program headers, to find the allocation space of this file */ 162 | f->min = (void *) -1; 163 | f->max = 0; 164 | curphdrl = f->prog + f->ehdr->e_phoff - f->ehdr->e_phentsize; 165 | 166 | for (phdri = 0; phdri < f->ehdr->e_phnum; phdri++) { 167 | curphdrl += f->ehdr->e_phentsize; 168 | curphdr = (ElfNative_Phdr *) curphdrl; 169 | 170 | /* perhaps check its location */ 171 | if (curphdr->p_type == PT_LOAD) { 172 | /* adjust min/max */ 173 | if ((void *) curphdr->p_vaddr < f->min) { 174 | f->min = (void *) curphdr->p_vaddr; 175 | } 176 | if ((void *) curphdr->p_vaddr + curphdr->p_memsz > f->max) { 177 | f->max = (void *) curphdr->p_vaddr + curphdr->p_memsz; 178 | } 179 | 180 | } else if (maybe && curphdr->p_type == PT_INTERP) { 181 | /* if we're only maybe-loading, check the loader */ 182 | if (strcmp((char *) (f->prog + curphdr->p_offset), "/usr/bin/gelfload-ld")) { 183 | /* wrong loader! */ 184 | return NULL; 185 | } 186 | 187 | } 188 | } 189 | 190 | /* with this size info, we can allocate the space */ 191 | f->memsz = f->max - f->min; 192 | 193 | /* if this is a binary, try to allocate it in place. elfload is addressed above 0x18000000 */ 194 | if (f->ehdr->e_type == ET_EXEC && f->max < (void *) 0x18000000) { 195 | f->loc = bbuffer(f->min, f->memsz); 196 | 197 | } else { 198 | f->loc = bbuffer(NULL, f->memsz); 199 | 200 | } 201 | memset(f->loc, 0, f->memsz); 202 | 203 | f->offset = f->loc - f->min; 204 | 205 | /* we have the space, so load it in */ 206 | curphdrl = f->prog + f->ehdr->e_phoff - f->ehdr->e_phentsize; 207 | for (phdri = 0; phdri < f->ehdr->e_phnum; phdri++) { 208 | curphdrl += f->ehdr->e_phentsize; 209 | curphdr = (ElfNative_Phdr *) curphdrl; 210 | 211 | /* perhaps load it in */ 212 | if (curphdr->p_type == PT_LOAD) { 213 | if (curphdr->p_filesz > 0) { 214 | /* OK, there's something to copy in, so do so */ 215 | memcpy((void *) curphdr->p_vaddr + f->offset, 216 | f->prog + curphdr->p_offset, 217 | curphdr->p_filesz); 218 | } 219 | 220 | } else if (curphdr->p_type == PT_DYNAMIC) { 221 | /* we need this to load in dependencies, et cetera */ 222 | f->dynamic = (ElfNative_Dyn *) (f->prog + curphdr->p_offset); 223 | 224 | } 225 | } 226 | 227 | /* now go through dynamic entries, looking for basic vital info */ 228 | for (curdyn = f->dynamic; curdyn && curdyn->d_tag != DT_NULL; curdyn++) { 229 | if (curdyn->d_tag == DT_STRTAB) { 230 | f->strtab = (char *) (curdyn->d_un.d_ptr + f->offset); 231 | 232 | } else if (curdyn->d_tag == DT_SYMTAB) { 233 | f->symtab = (ElfNative_Sym *) (curdyn->d_un.d_ptr + f->offset); 234 | 235 | } else if (curdyn->d_tag == DT_HASH) { 236 | f->hashtab = (ElfNative_Word *) (curdyn->d_un.d_ptr + f->offset); 237 | 238 | } else if (curdyn->d_tag == DT_RELA) { 239 | f->rela = (ElfNative_Rela *) (curdyn->d_un.d_ptr + f->offset); 240 | 241 | } else if (curdyn->d_tag == DT_RELASZ) { 242 | f->relasz = curdyn->d_un.d_val; 243 | 244 | } else if (curdyn->d_tag == DT_REL) { 245 | f->rel = (ElfNative_Rel *) (curdyn->d_un.d_ptr + f->offset); 246 | 247 | } else if (curdyn->d_tag == DT_RELSZ) { 248 | f->relsz = curdyn->d_un.d_val; 249 | 250 | } else if (curdyn->d_tag == DT_JMPREL) { 251 | f->jmprel = (void *) (curdyn->d_un.d_ptr + f->offset); 252 | 253 | } else if (curdyn->d_tag == DT_PLTRELSZ) { 254 | f->jmprelsz = curdyn->d_un.d_val; 255 | 256 | } 257 | } 258 | 259 | /* load in dependencies */ 260 | for (curdyn = f->dynamic; curdyn && curdyn->d_tag != DT_NULL; curdyn++) { 261 | if (curdyn->d_tag == DT_NEEDED) { 262 | loadELF(f->strtab + curdyn->d_un.d_val, instdir, 0); 263 | } 264 | } 265 | 266 | return f; 267 | } 268 | 269 | void relocateELFs() 270 | { 271 | int i; 272 | 273 | for (i = elfFileCount - 1; i >= 0; i--) { 274 | relocateELF(i, &(elfFiles[i])); 275 | } 276 | } 277 | 278 | void relocateELF(int fileNo, struct ELF_File *f) 279 | { 280 | /* do processor-specific relocation */ 281 | #if GELFLOAD_ARCH_i386 282 | #define REL_P ((ssize_t) (currel->r_offset + f->offset)) 283 | #define REL_S ((ssize_t) (findELFSymbol( \ 284 | f->strtab + f->symtab[ELFNATIVE_R_SYM(currel->r_info)].st_name, \ 285 | NULL, fileNo, -1, NULL))) 286 | #define REL_A (*((ssize_t *) REL_P)) 287 | #define WORD32_REL(to) REL_A = (ssize_t) (to) 288 | 289 | /* we ought to have rel and symtab defined */ 290 | if (f->rel && f->symtab) { 291 | ElfNative_Rel *currel = f->rel; 292 | for (; (void *) currel < (void *) f->rel + f->relsz; currel++) { 293 | switch (ELFNATIVE_R_TYPE(currel->r_info)) { 294 | case R_386_32: 295 | WORD32_REL(REL_S + REL_A); 296 | break; 297 | 298 | case R_386_PC32: 299 | WORD32_REL(REL_S + REL_A - REL_P); 300 | break; 301 | 302 | case R_386_COPY: 303 | { 304 | /* this is a bit more convoluted, as we need to find it in both places and copy */ 305 | ElfNative_Sym *localsym, *sosym; 306 | localsym = &(f->symtab[ELFNATIVE_R_SYM(currel->r_info)]); 307 | void *soptr = findELFSymbol( 308 | f->strtab + localsym->st_name, 309 | NULL, -1, fileNo, &sosym); 310 | 311 | /* OK, we should have both, so copy it over */ 312 | if (localsym && sosym) { 313 | memcpy((void *) (localsym->st_value + f->offset), 314 | soptr, sosym->st_size); 315 | } else { 316 | /* depend on localsym's size */ 317 | memcpy((void *) (localsym->st_value + f->offset), 318 | soptr, localsym->st_size); 319 | 320 | } 321 | 322 | break; 323 | } 324 | 325 | case R_386_GLOB_DAT: 326 | WORD32_REL(REL_S + REL_A); 327 | break; 328 | 329 | case R_386_RELATIVE: 330 | WORD32_REL(f->loc + REL_A); 331 | break; 332 | 333 | default: 334 | fprintf(stderr, "Unsupported relocation %d in %s\n", ELFNATIVE_R_TYPE(currel->r_info), f->nm); 335 | } 336 | } 337 | } 338 | 339 | if (f->jmprel && f->symtab) { 340 | ElfNative_Rel *currel = (ElfNative_Rel *) f->jmprel; 341 | for (; (void *) currel < f->jmprel + f->jmprelsz; currel++) { 342 | switch (ELFNATIVE_R_TYPE(currel->r_info)) { 343 | case R_386_JMP_SLOT: 344 | WORD32_REL(REL_S); 345 | break; 346 | } 347 | } 348 | } 349 | 350 | 351 | #elif GELFLOAD_ARCH_x86_64 352 | #define REL_P ((ssize_t) (currel->r_offset + f->offset)) 353 | #define REL_S ((ssize_t) (findELFSymbol( \ 354 | f->strtab + f->symtab[ELFNATIVE_R_SYM(currel->r_info)].st_name, \ 355 | NULL, fileNo, -1, NULL))) 356 | #define REL_A (*((ssize_t *) REL_P)) 357 | #define WORD32_REL(to) REL_A = (int32_t) (to) 358 | #define WORD64_REL(to) REL_A = (ssize_t) (to) 359 | 360 | /* we ought to have rel and symtab defined */ 361 | if (f->rela && f->symtab) { 362 | ElfNative_Rela *currel = f->rela; 363 | for (; (void *) currel < (void *) f->rela + f->relasz; currel++) { 364 | switch (ELFNATIVE_R_TYPE(currel->r_info)) { 365 | case R_X86_64_64: 366 | WORD64_REL(REL_S + REL_A); 367 | break; 368 | 369 | case R_X86_64_PC32: 370 | WORD32_REL(REL_S + REL_A - REL_P); 371 | break; 372 | 373 | case R_X86_64_COPY: 374 | { 375 | /* this is a bit more convoluted, as we need to find it in both places and copy */ 376 | ElfNative_Sym *localsym, *sosym; 377 | localsym = &(f->symtab[ELFNATIVE_R_SYM(currel->r_info)]); 378 | void *soptr = findELFSymbol( 379 | f->strtab + localsym->st_name, 380 | NULL, -1, fileNo, &sosym); 381 | 382 | /* OK, we should have both, so copy it over */ 383 | if (localsym && sosym) { 384 | memcpy((void *) (localsym->st_value + f->offset), 385 | soptr, sosym->st_size); 386 | } else { 387 | /* depend on localsym's size */ 388 | memcpy((void *) (localsym->st_value + f->offset), 389 | soptr, localsym->st_size); 390 | 391 | } 392 | 393 | break; 394 | } 395 | 396 | case R_X86_64_GLOB_DAT: 397 | WORD64_REL(REL_S + REL_A); 398 | break; 399 | 400 | case R_X86_64_RELATIVE: 401 | WORD64_REL(f->loc + REL_A); 402 | break; 403 | 404 | default: 405 | fprintf(stderr, "Unsupported relocation %d in %s\n", (int) ELFNATIVE_R_TYPE(currel->r_info), f->nm); 406 | } 407 | } 408 | } 409 | 410 | if (f->jmprel && f->symtab) { 411 | ElfNative_Rela *currel = (ElfNative_Rela *) f->jmprel; 412 | for (; (void *) currel < (void *) f->jmprel + f->jmprelsz; currel++) { 413 | switch (ELFNATIVE_R_TYPE(currel->r_info)) { 414 | case R_X86_64_JUMP_SLOT: 415 | WORD64_REL(REL_S); 416 | break; 417 | 418 | default: 419 | fprintf(stderr, "Unsupported jmprel relocation %d in %s\n", (int) ELFNATIVE_R_TYPE(currel->r_info), f->nm); 420 | } 421 | } 422 | } 423 | 424 | 425 | #else 426 | #error Unsupported architecture. 427 | #endif 428 | } 429 | 430 | /* Initialize every ELF loaded /except/ for f (usually the binary) */ 431 | void initELF(struct ELF_File *except) 432 | { 433 | int i; 434 | struct ELF_File *f; 435 | ElfNative_Dyn *dyn; 436 | 437 | for (i = elfFileCount - 1; i >= 0; i--) { 438 | f = &(elfFiles[i]); 439 | if (f == except) continue; 440 | 441 | /* init is in the dynamic section */ 442 | if (f->dynamic == NULL) continue; 443 | for (dyn = f->dynamic; dyn && dyn->d_tag != DT_NULL; dyn++) { 444 | if (dyn->d_tag == DT_INIT) { 445 | /* call it */ 446 | ((void(*)()) (dyn->d_un.d_ptr + f->offset))(); 447 | break; 448 | } 449 | } 450 | } 451 | } 452 | 453 | /* Find a symbol within the currently loaded ELF files 454 | * localin: The number of the current file, where STB_LOCAL symbols are OK 455 | * notin: Do not bind to symbols in this file 456 | * Either can be -1 */ 457 | void *findELFSymbol(const char *nm, struct ELF_File *onlyin, int localin, int notin, ElfNative_Sym **syminto) 458 | { 459 | int i; 460 | struct ELF_File *f; 461 | ElfNative_Word hash = elf_hash((unsigned char *) nm); 462 | ElfNative_Word bucket, index; 463 | ElfNative_Sym *sym; 464 | void *hostsym; 465 | if (syminto) *syminto = NULL; 466 | 467 | if (nm[0] == '\0') return NULL; 468 | 469 | for (i = 0; i < elfFileCount; i++) { 470 | if (i == notin) continue; 471 | 472 | f = &(elfFiles[i]); 473 | if (onlyin && f != onlyin) continue; 474 | 475 | /* if this is a host library, just try the host method */ 476 | if (f->hostlib == HOSTLIB_HOST) { 477 | char lsym[1024]; 478 | snprintf(lsym, 1024, "gelfload__%s", nm); 479 | 480 | #if defined(HAVE_DLFCN_H) 481 | hostsym = dlsym(f->prog, lsym); 482 | if (hostsym) return hostsym; 483 | hostsym = dlsym(f->prog, nm); 484 | if (hostsym) return hostsym; 485 | continue; 486 | #elif defined(__WIN32) 487 | char csym[1024]; 488 | int isimp = 0; 489 | 490 | /* Remove _imp__ if it's present */ 491 | if (strncmp(nm, "_imp__", 6) == 0) { 492 | isimp = 1; 493 | nm += 6; 494 | snprintf(lsym, 1024, "gelfload__%s", nm); 495 | } 496 | 497 | /* Try adding a _ first, to get the cdecl version */ 498 | snprintf(csym, 1024, "_%s", lsym); 499 | hostsym = GetProcAddress(f->prog, csym); 500 | if (hostsym == NULL) 501 | hostsym = GetProcAddress(f->prog, lsym); 502 | if (hostsym == NULL) { 503 | snprintf(csym, 1024, "_%s", nm); 504 | hostsym = GetProcAddress(f->proc, csym); 505 | } 506 | if (hostsym == NULL) 507 | hostsym = GetProcAddress(f->prog, nm); 508 | if (hostsym) { 509 | if (isimp) { 510 | /* Need a pointer to this pointer */ 511 | void **pptr = (void **) malloc(sizeof(void*)); 512 | if (pptr == NULL) { 513 | perror("malloc"); 514 | exit(1); 515 | } 516 | *pptr = hostsym; 517 | return (void *) pptr; 518 | 519 | } else { 520 | return hostsym; 521 | 522 | } 523 | } 524 | #endif 525 | continue; 526 | 527 | } else if (f->hostlib == HOSTLIB_DL) { 528 | hostsym = elfload_dl(nm); 529 | if (hostsym) return hostsym; 530 | continue; 531 | 532 | } 533 | 534 | /* figure out the bucket ... */ 535 | bucket = hash % ELFFILE_NBUCKET(f); 536 | 537 | /* then find the chain entry */ 538 | index = ELFFILE_BUCKET(f, bucket); 539 | 540 | /* and work our way through the chain */ 541 | for (; index != STN_UNDEF; index = ELFFILE_CHAIN(f, index)) { 542 | sym = &(f->symtab[index]); 543 | 544 | /* see if it's defined */ 545 | if (strcmp(f->strtab + sym->st_name, nm) == 0 && 546 | (i == localin || ELFNATIVE_ST_BIND(sym->st_info) != STB_LOCAL) && 547 | sym->st_shndx != SHN_UNDEF) { 548 | /* we found our symbol! */ 549 | if (syminto != NULL) { 550 | *syminto = sym; 551 | } 552 | return (void *) (sym->st_value + f->offset); 553 | } 554 | } 555 | } 556 | 557 | /* uh oh, not found! */ 558 | fprintf(stderr, "Symbol undefined: '%s'\n", nm); 559 | return NULL; 560 | } 561 | 562 | /* The standard ELF hash function */ 563 | ElfNative_Word elf_hash(const unsigned char *name) 564 | { 565 | ElfNative_Word h = 0, g; 566 | 567 | while (*name) { 568 | h = (h << 4) + *name++; 569 | if (g = h & 0xf0000000) 570 | h ^= g >> 24; 571 | h &= ~g; 572 | } 573 | return h; 574 | } 575 | 576 | /* A handy function to read a file or mmap it, as appropriate */ 577 | void readFile(const char *nm, const char *instdir, struct ELF_File *ef) 578 | { 579 | /* try with instdir */ 580 | char *longnm = malloc(strlen(nm) + strlen(instdir) + 18); 581 | if (longnm == NULL) { 582 | perror("malloc"); 583 | exit(1); 584 | } 585 | sprintf(longnm, "%s/../lib/gelfload/%s", instdir, nm); 586 | 587 | #ifdef HAVE_MMAP 588 | { 589 | void *buf; 590 | struct stat sbuf; 591 | int fd; 592 | 593 | /* use mmap. First, open the file and get its length */ 594 | fd = open(nm, O_RDONLY); 595 | if (fd == -1) { 596 | fd = open(longnm, O_RDONLY); 597 | 598 | if (fd == -1) { 599 | perror(nm); 600 | exit(1); 601 | } 602 | } 603 | free(longnm); 604 | if (fstat(fd, &sbuf) < 0) { 605 | perror(nm); 606 | exit(1); 607 | } 608 | 609 | /* then mmap it */ 610 | buf = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 611 | if (buf == NULL) { 612 | perror("mmap"); 613 | exit(1); 614 | } 615 | 616 | close(fd); 617 | 618 | /* and put it in ef */ 619 | ef->prog = buf; 620 | ef->proglen = sbuf.st_size; 621 | } 622 | #else 623 | { 624 | char *buf; 625 | int bufsz, rdtotal, rd; 626 | FILE *f; 627 | 628 | /* OK, use stdio */ 629 | f = fopen(nm, "rb"); 630 | if (f == NULL) { 631 | f = fopen(longnm, "rb"); 632 | 633 | if (f == NULL) { 634 | perror(nm); 635 | exit(1); 636 | } 637 | } 638 | free(longnm); 639 | 640 | /* start with a 512-byte buffer */ 641 | bufsz = 512; 642 | buf = (char *) malloc(bufsz); 643 | if (buf == NULL) { 644 | perror("malloc"); 645 | exit(1); 646 | } 647 | 648 | /* and read in the file */ 649 | rdtotal = 0; 650 | while ((rd = fread(buf + rdtotal, 1, bufsz - rdtotal, f)) != 0) { 651 | rdtotal += rd; 652 | if (rdtotal != bufsz) { 653 | /* done reading */ 654 | break; 655 | 656 | } else { 657 | bufsz <<= 1; 658 | buf = realloc(buf, bufsz); 659 | if (buf == NULL) { 660 | perror("realloc"); 661 | exit(1); 662 | } 663 | } 664 | } 665 | if (ferror(f)) { 666 | perror(nm); 667 | exit(1); 668 | } 669 | fclose(f); 670 | 671 | /* now put it in ef */ 672 | ef->prog = buf; 673 | ef->proglen = rdtotal; 674 | } 675 | #endif 676 | } 677 | 678 | /* The finalization function for readFile */ 679 | void closeFile(struct ELF_File *ef) 680 | { 681 | #ifdef HAVE_MMAP 682 | munmap(ef->prog, ef->proglen); 683 | #else 684 | free(ef->prog); 685 | #endif 686 | } 687 | -------------------------------------------------------------------------------- /src/elfload.h: -------------------------------------------------------------------------------- 1 | #ifndef ELFLOAD_H 2 | #define ELFLOAD_H 3 | 4 | #include 5 | 6 | #include "elfnative.h" 7 | 8 | #define HOSTLIB_NOT 0 9 | #define HOSTLIB_HOST 1 10 | #define HOSTLIB_DL 2 11 | 12 | /* Basic structure for ELF files mid-load */ 13 | struct ELF_File { 14 | char *nm; 15 | 16 | /* if this is actually a host library, this is set to 1 */ 17 | char hostlib; 18 | 19 | /* the complete program, in memory */ 20 | void *prog; 21 | size_t proglen; 22 | 23 | /* same pointer, actually */ 24 | ElfNative_Ehdr *ehdr; 25 | 26 | /* the size in memory of this file */ 27 | ssize_t memsz; 28 | 29 | /* the minimum and maximum position of the loaded file, ideally */ 30 | void *min, *max; 31 | 32 | /* the actual location where this file was loaded */ 33 | void *loc; 34 | 35 | /* the offset of this file's real loaded location from its internal location */ 36 | ssize_t offset; 37 | 38 | /* the dynamic entries table */ 39 | ElfNative_Dyn *dynamic; 40 | 41 | /* the string table */ 42 | char *strtab; 43 | 44 | /* and symbol table */ 45 | ElfNative_Sym *symtab; 46 | 47 | /* with its associated hash table */ 48 | ElfNative_Word *hashtab; 49 | #define ELFFILE_NBUCKET(f) ((f)->hashtab[0]) 50 | #define ELFFILE_NCHAIN(f) ((f)->hashtab[1]) 51 | #define ELFFILE_BUCKET(f, i) ((f)->hashtab[(i) + 2]) 52 | #define ELFFILE_CHAIN(f, i) ((f)->hashtab[(i) + ELFFILE_NBUCKET(f) + 2]) 53 | 54 | /* relocation table(s) */ 55 | ElfNative_Rel *rel; 56 | size_t relsz; 57 | ElfNative_Rela *rela; 58 | size_t relasz; 59 | void *jmprel; 60 | size_t jmprelsz; 61 | }; 62 | 63 | struct ELF_File *loadELF(const char *nm, const char *instdir, int maybe); 64 | void relocateELFs(); 65 | void relocateELF(int fileNo, struct ELF_File *f); 66 | void initELF(struct ELF_File *except); 67 | void readFile(const char *nm, const char *instdir, struct ELF_File *ef); 68 | void closeFile(struct ELF_File *ef); 69 | void *findELFSymbol(const char *nm, struct ELF_File *onlyin, int localin, int notin, 70 | ElfNative_Sym **syminto); 71 | ElfNative_Word elf_hash(const unsigned char *name); 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/elfload_dlfcn.h: -------------------------------------------------------------------------------- 1 | /* dlfcn for elfload-loaded ELFs */ 2 | 3 | #ifndef ELFLOAD_DLFCN_H 4 | #define ELFLOAD_DLFCN_H 5 | 6 | extern char *elfload_dlinstdir; 7 | 8 | void *elfload_dlopen(const char *filename, int flag); 9 | char *elfload_dlerror(void); 10 | void *elfload_dlsym(void *handle, const char *symbol); 11 | int elfload_dlclose(void *handle); 12 | 13 | /* return one of these functions by their name */ 14 | void *elfload_dl(const char *fname); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/elfload_exec.h: -------------------------------------------------------------------------------- 1 | /* From a loader, pop off our entire stack and execute the loaded program */ 2 | 3 | /* 4 | * Copyright (c) 2007, 2012 Gregor Richards 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to 8 | * deal in the Software without restriction, including without limitation the 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | * sell copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 | * IN THE SOFTWARE. 20 | */ 21 | 22 | #include "config.h" 23 | 24 | #if GELFLOAD_ARCH_i386 25 | #define WITHSTACK_JMP(newstack, newloc) \ 26 | asm("mov %0, %%esp\n" \ 27 | "jmp *%1\n" \ 28 | : \ 29 | : "r"(newstack), "r"(newloc)); 30 | 31 | #elif GELFLOAD_ARCH_x86_64 32 | #define WITHSTACK_JMP(newstack, newloc) \ 33 | asm("mov %0, %%rsp\n" \ 34 | "jmp *%1\n" \ 35 | : \ 36 | : "r"(newstack), "r"(newloc)); 37 | 38 | #else 39 | #error No assembly code for subprocess execution known. 40 | #endif 41 | -------------------------------------------------------------------------------- /src/elfnative.h: -------------------------------------------------------------------------------- 1 | #ifndef ELFNATIVE_H 2 | #define ELFNATIVE_H 3 | 4 | #include "../config.h" 5 | #include "elfload_elf.h" 6 | 7 | #if SIZEOF_VOID_P == 4 8 | 9 | #define ElfNative_Ehdr Elf32_Ehdr 10 | #define ElfNative_Phdr Elf32_Phdr 11 | #define ElfNative_Dyn Elf32_Dyn 12 | #define ElfNative_Sym Elf32_Sym 13 | #define ElfNative_Word Elf32_Word 14 | #define ElfNative_Rel Elf32_Rel 15 | #define ElfNative_Rela Elf32_Rela 16 | 17 | #define ELFNATIVE_ST_BIND ELF32_ST_BIND 18 | #define ELFNATIVE_R_SYM ELF32_R_SYM 19 | #define ELFNATIVE_R_TYPE ELF32_R_TYPE 20 | 21 | #elif SIZEOF_VOID_P == 8 22 | 23 | #define ElfNative_Ehdr Elf64_Ehdr 24 | #define ElfNative_Phdr Elf64_Phdr 25 | #define ElfNative_Dyn Elf64_Dyn 26 | #define ElfNative_Sym Elf64_Sym 27 | #define ElfNative_Word Elf64_Word 28 | #define ElfNative_Rel Elf64_Rel 29 | #define ElfNative_Rela Elf64_Rela 30 | 31 | #define ELFNATIVE_ST_BIND ELF32_ST_BIND 32 | #define ELFNATIVE_R_SYM ELF64_R_SYM 33 | #define ELFNATIVE_R_TYPE ELF64_R_TYPE 34 | 35 | #else 36 | 37 | #error Unsupported bitwidth. 38 | 39 | #endif 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef __WIN32 6 | #include 7 | #endif 8 | 9 | #include "elfload.h" 10 | #include "elfload_dlfcn.h" 11 | #include "elfload_exec.h" 12 | #include "whereami.h" 13 | 14 | int main(int argc, char **argv, char **envp) 15 | { 16 | struct ELF_File *f; 17 | void **newstack; 18 | int i, envc, progarg; 19 | char *dir, *fil; 20 | int maybe = 0; 21 | 22 | progarg = -1; 23 | for (i = 1; i < argc; i++) { 24 | if (argv[i][0] == '-') { 25 | if (!strcmp(argv[i], "-m")) { 26 | maybe = 1; 27 | } else if (!strcmp(argv[i], "--")) { 28 | progarg = i + 1; 29 | break; 30 | } 31 | } else { 32 | progarg = i; 33 | break; 34 | } 35 | } 36 | if (progarg == -1) { 37 | fprintf(stderr, "Use: elfload [-m] [arguments]\n"); 38 | return 1; 39 | } 40 | 41 | whereAmI(argv[0], &dir, &fil); 42 | elfload_dlinstdir = dir; 43 | 44 | /* load them all in */ 45 | f = loadELF(argv[progarg], dir, maybe); 46 | 47 | if (!f) { 48 | /* try just execing it */ 49 | execv(argv[progarg], argv + progarg); 50 | fprintf(stderr, "Failed to load %s.\n", argv[progarg]); 51 | return 1; 52 | } 53 | 54 | /* relocate them */ 55 | relocateELFs(); 56 | 57 | /* initialize .so files */ 58 | initELF(f); 59 | 60 | /* make its stack */ 61 | for (envc = 0; envp[envc]; envc++); 62 | newstack = (void**) 63 | alloca((argc + envc + 2) * sizeof(void*)); 64 | newstack[0] = (void*) (size_t) (argc - progarg); 65 | for (i = progarg; i < argc; i++) { 66 | newstack[i - progarg + 1] = (void*) argv[i]; 67 | } 68 | newstack[i - progarg + 1] = NULL; 69 | 70 | for (i = 0; i < envc; i++) { 71 | newstack[i-progarg+argc+2] = (void*) envp[i]; 72 | } 73 | newstack[i-progarg+argc+2] = NULL; 74 | 75 | /* and call it */ 76 | WITHSTACK_JMP(newstack, f->ehdr->e_entry + f->offset); 77 | } 78 | -------------------------------------------------------------------------------- /src/whereami.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2005, 2006 Gregor Richards 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | * this software and associated documentation files (the "Software"), to deal in 6 | * the Software without restriction, including without limitation the rights to 7 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8 | * of the Software, and to permit persons to whom the Software is furnished to do 9 | * so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | /* Separate a full path into a directory and file component (internal) 31 | * full: Full path 32 | * dir: Where to put the dir component 33 | * fil: Where to put the file component */ 34 | void dirAndFil(const char *full, char **dir, char **fil) 35 | { 36 | *dir = strdup(full); 37 | *fil = strrchr(*dir, '/'); 38 | if (*fil) { 39 | **fil = '\0'; 40 | (*fil)++; 41 | *fil = strdup(*fil); 42 | } else { 43 | *fil = (char *) malloc(1); 44 | if (!(*fil)) { 45 | perror("malloc"); 46 | exit(1); 47 | } 48 | **fil = '\0'; 49 | } 50 | } 51 | 52 | /* Figure out where a binary is installed 53 | * argvz: argv[0] 54 | * dir: Where to put the directory component 55 | * fil: Where to put the filename component 56 | * returns a pointer to dir or NULL for failure */ 57 | char *whereAmI(const char *argvz, char **dir, char **fil) 58 | { 59 | char *workd, *path, *retname; 60 | char *pathelem[1024]; 61 | int i, j, osl; 62 | struct stat sbuf; 63 | char *argvzd = strdup(argvz); 64 | if (!argvzd) { perror("strdup"); exit(1); } 65 | 66 | #ifdef __WIN32 67 | for (i = 0; argvzd[i]; i++) { 68 | if (argvzd[i] == '\\') { 69 | argvzd[i] = '/'; 70 | } 71 | } 72 | #endif 73 | 74 | /* 1: full path, yippee! */ 75 | if (argvzd[0] == '/') { 76 | dirAndFil(argvzd, dir, fil); 77 | return argvzd; 78 | } 79 | 80 | #ifdef __WIN32 81 | /* 1.5: full path on Windows */ 82 | if (argvzd[1] == ':' && 83 | argvzd[2] == '/') { 84 | dirAndFil(argvzd, dir, fil); 85 | return argvzd; 86 | } 87 | #endif 88 | 89 | /* 2: relative path */ 90 | if (strchr(argvzd, '/')) { 91 | workd = (char *) malloc(1024 * sizeof(char)); 92 | if (!workd) { perror("malloc"); exit(1); } 93 | 94 | if (getcwd(workd, 1024)) { 95 | retname = (char *) malloc((strlen(workd) + strlen(argvzd) + 2) * sizeof(char)); 96 | if (!retname) { perror("malloc"); exit(1); } 97 | 98 | sprintf(retname, "%s/%s", workd, argvzd); 99 | free(workd); 100 | 101 | dirAndFil(retname, dir, fil); 102 | free(argvzd); 103 | return retname; 104 | } 105 | } 106 | 107 | /* 3: worst case: find in PATH */ 108 | path = getenv("PATH"); 109 | if (path == NULL) { 110 | return NULL; 111 | } 112 | path = strdup(path); 113 | 114 | /* tokenize by : */ 115 | memset(pathelem, 0, 1024 * sizeof(char *)); 116 | pathelem[0] = path; 117 | i = 1; 118 | osl = strlen(path); 119 | for (j = 0; j < osl; j++) { 120 | for (; path[j] != '\0' && path[j] != ':'; j++); 121 | 122 | if (path[j] == ':') { 123 | path[j] = '\0'; 124 | 125 | j++; 126 | pathelem[i++] = path + j; 127 | } 128 | } 129 | 130 | /* go through every pathelem */ 131 | for (i = 0; pathelem[i]; i++) { 132 | retname = (char *) malloc((strlen(pathelem[i]) + strlen(argvzd) + 2) * sizeof(char)); 133 | if (!retname) { perror("malloc"); exit(1); } 134 | 135 | sprintf(retname, "%s/%s", pathelem[i], argvzd); 136 | 137 | if (stat(retname, &sbuf) == -1) { 138 | free(retname); 139 | continue; 140 | } 141 | 142 | if (sbuf.st_mode & S_IXUSR) { 143 | dirAndFil(retname, dir, fil); 144 | free(argvzd); 145 | return retname; 146 | } 147 | 148 | free(retname); 149 | } 150 | 151 | /* 4: can't find it */ 152 | dir = NULL; 153 | fil = NULL; 154 | free(argvzd); 155 | return NULL; 156 | } 157 | -------------------------------------------------------------------------------- /src/whereami.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2005 Gregor Richards 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | * this software and associated documentation files (the "Software"), to deal in 6 | * the Software without restriction, including without limitation the rights to 7 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8 | * of the Software, and to permit persons to whom the Software is furnished to do 9 | * so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | * SOFTWARE. 21 | */ 22 | 23 | #ifndef WHEREAMI_H 24 | #define WHEREAMI_H 25 | 26 | /* Figure out where a binary is installed 27 | * argvz: argv[0] 28 | * dir: Where to put the directory component 29 | * fil: Where to put the filename component 30 | * returns a pointer to dir or NULL for failure */ 31 | char *whereAmI(const char *argvz, char **dir, char **fil); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /test/common/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | LD=ld 3 | CFLAGS= 4 | LDFLAGS=--dynamic-linker=/usr/bin/gelfload-ld 5 | SOFLAGS=-shared -soname= 6 | 7 | TESTSTATIC_OBJS=teststatic.o 8 | TESTHOST_OBJS=testhost.o 9 | TESTSO_OBJS=testso.o 10 | TESTDL_OBJS=testdl.o 11 | LIBC_OBJS=libc_wrap.o 12 | 13 | all: teststatic testhost testso.so testdl libc.so 14 | 15 | teststatic: $(TESTSTATIC_OBJS) 16 | $(LD) $(LDFLAGS) $(TESTSTATIC_OBJS) -o teststatic 17 | 18 | testhost: $(TESTHOST_OBJS) testso.so 19 | $(LD) $(LDFLAGS) $(TESTHOST_OBJS) testso.so -o testhost 20 | 21 | testso.so: $(TESTSO_OBJS) 22 | $(LD) $(LDFLAGS) $(TESTSO_OBJS) $(SOFLAGS)testso.so -o testso.so 23 | 24 | testdl: libc.so $(TESTDL_OBJS) 25 | $(LD) $(LDFLAGS) $(TESTDL_OBJS) libc.so -o testdl 26 | 27 | libc.so: $(LIBC_OBJS) 28 | $(LD) $(LDFLAGS) $(LIBC_OBJS) $(SOFLAGS)libhost_.so -o libc.so 29 | 30 | .s.o: 31 | $(CC) $(CFLAGS) -c $< -o $@ 32 | 33 | .c.o: 34 | $(CC) $(CFLAGS) -fPIC -c $< -o $@ 35 | 36 | clean: 37 | rm -f teststatic $(TESTSTATIC_OBJS) 38 | rm -f testhost $(TESTHOST_OBJS) 39 | rm -f testso.so $(TESTSO_OBJS) 40 | rm -f testdl $(TESTDL_OBJS) 41 | rm -f libc.so $(LIBC_OBJS) 42 | -------------------------------------------------------------------------------- /test/common/libc_wrap.c: -------------------------------------------------------------------------------- 1 | void puts(){} 2 | void printf(){} 3 | void exit(){} 4 | -------------------------------------------------------------------------------- /test/common/testdl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void _start() 5 | { 6 | printf("Hello, world!\n"); 7 | exit(0); 8 | while (1); 9 | } 10 | -------------------------------------------------------------------------------- /test/i686-pc-linux-gnu/Makefile: -------------------------------------------------------------------------------- 1 | include ../common/Makefile 2 | -------------------------------------------------------------------------------- /test/i686-pc-linux-gnu/libc_wrap.c: -------------------------------------------------------------------------------- 1 | #include "../common/libc_wrap.c" 2 | -------------------------------------------------------------------------------- /test/i686-pc-linux-gnu/testdl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregorR/gelfload/04d505fd1e5d2695a9076aa54ff8b193b1989d7f/test/i686-pc-linux-gnu/testdl -------------------------------------------------------------------------------- /test/i686-pc-linux-gnu/testdl.c: -------------------------------------------------------------------------------- 1 | #include "../common/testdl.c" 2 | -------------------------------------------------------------------------------- /test/i686-pc-linux-gnu/testhost: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregorR/gelfload/04d505fd1e5d2695a9076aa54ff8b193b1989d7f/test/i686-pc-linux-gnu/testhost -------------------------------------------------------------------------------- /test/i686-pc-linux-gnu/testhost.s: -------------------------------------------------------------------------------- 1 | .globl _start 2 | 3 | _start: 4 | mov $4, %eax 5 | mov $1, %ebx 6 | movl $_str, %ecx 7 | mov $14, %edx 8 | int $0x80 9 | _loop: 10 | jmp _loop 11 | -------------------------------------------------------------------------------- /test/i686-pc-linux-gnu/testso.s: -------------------------------------------------------------------------------- 1 | .section .rodata 2 | .globl _str 3 | 4 | _str: 5 | .string "Hello, world!\n" 6 | .size _str,.-_str 7 | -------------------------------------------------------------------------------- /test/i686-pc-linux-gnu/testso.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregorR/gelfload/04d505fd1e5d2695a9076aa54ff8b193b1989d7f/test/i686-pc-linux-gnu/testso.so -------------------------------------------------------------------------------- /test/i686-pc-linux-gnu/teststatic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregorR/gelfload/04d505fd1e5d2695a9076aa54ff8b193b1989d7f/test/i686-pc-linux-gnu/teststatic -------------------------------------------------------------------------------- /test/i686-pc-linux-gnu/teststatic.s: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl _str 3 | 4 | _strdat: 5 | .string "Hello, world!\n" 6 | 7 | _str: 8 | .long _strdat 9 | 10 | _start: 11 | mov $4, %eax 12 | mov $1, %ebx 13 | mov _str, %ecx 14 | mov $14, %edx 15 | int $0x80 16 | _loop: 17 | jmp _loop 18 | -------------------------------------------------------------------------------- /test/x86_64-pc-linux-gnu/Makefile: -------------------------------------------------------------------------------- 1 | include ../common/Makefile 2 | -------------------------------------------------------------------------------- /test/x86_64-pc-linux-gnu/libc_wrap.c: -------------------------------------------------------------------------------- 1 | #include "../common/libc_wrap.c" 2 | -------------------------------------------------------------------------------- /test/x86_64-pc-linux-gnu/testdl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregorR/gelfload/04d505fd1e5d2695a9076aa54ff8b193b1989d7f/test/x86_64-pc-linux-gnu/testdl -------------------------------------------------------------------------------- /test/x86_64-pc-linux-gnu/testdl.c: -------------------------------------------------------------------------------- 1 | #include "../common/testdl.c" 2 | -------------------------------------------------------------------------------- /test/x86_64-pc-linux-gnu/testhost: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregorR/gelfload/04d505fd1e5d2695a9076aa54ff8b193b1989d7f/test/x86_64-pc-linux-gnu/testhost -------------------------------------------------------------------------------- /test/x86_64-pc-linux-gnu/testhost.s: -------------------------------------------------------------------------------- 1 | .globl _start 2 | 3 | _start: 4 | mov $4, %eax 5 | mov $1, %ebx 6 | movl $_str, %ecx 7 | mov $14, %edx 8 | int $0x80 9 | _loop: 10 | jmp _loop 11 | -------------------------------------------------------------------------------- /test/x86_64-pc-linux-gnu/testso.s: -------------------------------------------------------------------------------- 1 | .section .rodata 2 | .globl _str 3 | 4 | _str: 5 | .string "Hello, world!\n" 6 | .size _str,.-_str 7 | -------------------------------------------------------------------------------- /test/x86_64-pc-linux-gnu/testso.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregorR/gelfload/04d505fd1e5d2695a9076aa54ff8b193b1989d7f/test/x86_64-pc-linux-gnu/testso.so -------------------------------------------------------------------------------- /test/x86_64-pc-linux-gnu/teststatic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregorR/gelfload/04d505fd1e5d2695a9076aa54ff8b193b1989d7f/test/x86_64-pc-linux-gnu/teststatic -------------------------------------------------------------------------------- /test/x86_64-pc-linux-gnu/teststatic.s: -------------------------------------------------------------------------------- 1 | .globl _start 2 | .globl _str 3 | 4 | _strdat: 5 | .string "Hello, world!\n" 6 | 7 | _str: 8 | .long _strdat 9 | 10 | _start: 11 | mov $4, %eax 12 | mov $1, %ebx 13 | mov _str, %ecx 14 | mov $14, %edx 15 | int $0x80 16 | _loop: 17 | jmp _loop 18 | --------------------------------------------------------------------------------