├── NEWS ├── TODO ├── packages ├── deb │ ├── compat │ ├── libcoredumper1.dirs │ ├── libcoredumper1.install │ ├── docs │ ├── libcoredumper-dev.dirs │ ├── libcoredumper-dev.install │ ├── README │ ├── changelog │ ├── control │ ├── copyright │ └── rules ├── rpm.sh ├── rpm │ └── rpm.spec └── deb.sh ├── AUTHORS ├── svn-commit.tmp ├── src ├── libcoredumper.sym ├── linuxthreads.h ├── thread_lister.c ├── config.h.in ├── thread_lister.h ├── google │ └── coredumper.h ├── coredumper.c ├── linux_syscall_support_unittest.cc └── elfcore.h ├── COPYING ├── configure.ac ├── README ├── examples ├── Makefile └── tftpd.c ├── compile ├── man ├── CoreDumpParameters.man ├── WriteCoreDump.man └── GetCoreDump.man ├── mkinstalldirs ├── ChangeLog ├── Makefile.am ├── INSTALL ├── install-sh ├── missing └── depcomp /NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/deb/compat: -------------------------------------------------------------------------------- 1 | 4 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | opensource@google.com 2 | 3 | -------------------------------------------------------------------------------- /packages/deb/libcoredumper1.dirs: -------------------------------------------------------------------------------- 1 | usr/lib 2 | -------------------------------------------------------------------------------- /packages/deb/libcoredumper1.install: -------------------------------------------------------------------------------- 1 | usr/lib/lib*.so.* 2 | debian/tmp/usr/lib/lib*.so.* 3 | -------------------------------------------------------------------------------- /svn-commit.tmp: -------------------------------------------------------------------------------- 1 | Version 1.0 2 | --This line, and those below, will be ignored-- 3 | 4 | A . 5 | -------------------------------------------------------------------------------- /packages/deb/docs: -------------------------------------------------------------------------------- 1 | AUTHORS 2 | COPYING 3 | ChangeLog 4 | INSTALL 5 | NEWS 6 | README 7 | TODO 8 | examples 9 | -------------------------------------------------------------------------------- /packages/deb/libcoredumper-dev.dirs: -------------------------------------------------------------------------------- 1 | usr/lib 2 | usr/include 3 | usr/include/google 4 | usr/share 5 | usr/share/man 6 | usr/share/man/man3 7 | -------------------------------------------------------------------------------- /packages/deb/libcoredumper-dev.install: -------------------------------------------------------------------------------- 1 | usr/include/google/* 2 | usr/lib/lib*.so 3 | usr/lib/lib*.a 4 | usr/lib/*.la 5 | usr/share/man/man3/* 6 | debian/tmp/usr/include/google/* 7 | debian/tmp/usr/lib/lib*.so 8 | debian/tmp/usr/lib/lib*.a 9 | debian/tmp/usr/lib/*.la 10 | -------------------------------------------------------------------------------- /packages/deb/README: -------------------------------------------------------------------------------- 1 | The list of files here isn't complete. For a step-by-step guide on 2 | how to set this package up correctly, check out 3 | http://www.debian.org/doc/maint-guide/ 4 | 5 | Most of the files that are in this directory are boilerplate. 6 | However, you may need to change the list of binary-arch dependencies 7 | in 'rules'. 8 | -------------------------------------------------------------------------------- /src/libcoredumper.sym: -------------------------------------------------------------------------------- 1 | COREDUMPER_COMPRESSED 2 | COREDUMPER_BZIP2_COMPRESSED 3 | COREDUMPER_GZIP_COMPRESSED 4 | COREDUMPER_COMPRESS_COMPRESSED 5 | COREDUMPER_TRY_BZIP2_COMPRESSED 6 | COREDUMPER_TRY_GZIP_COMPRESSED 7 | COREDUMPER_TRY_COMPRESS_COMPRESSED 8 | COREDUMPER_UNCOMPRESSED 9 | GetCoreDump 10 | GetCompressedCoreDump 11 | GetCoreDumpWith 12 | WriteCoreDump 13 | WriteCoreDumpWith 14 | WriteCoreDumpLimited 15 | WriteCoreDumpLimitedByPriority 16 | WriteCompressedCoreDump 17 | ClearCoreDumpParametersInternal 18 | SetCoreDumpCompressed 19 | SetCoreDumpLimited 20 | SetCoreDumpLimitedByPriority 21 | SetCoreDumpNotes 22 | -------------------------------------------------------------------------------- /packages/deb/changelog: -------------------------------------------------------------------------------- 1 | libcoredumper (1.2.1-1) unstable; urgency=low 2 | 3 | * Upgraded to version 1.2.1. 4 | 5 | -- Google Inc. Fri, 4 Apr 2008 09:41:51 -0800 6 | 7 | libcoredumper (1.1-1) unstable; urgency=low 8 | 9 | * Upgraded to version 1.1. 10 | 11 | -- Google Inc. Tue, 20 Feb 2007 15:07:03 -0800 12 | 13 | libcoredumper (1.0-1) unstable; urgency=low 14 | 15 | * Upgraded to version 1.0. 16 | 17 | -- Google Inc. Wed, 15 Feb 2007 16:24:32 -0800 18 | 19 | libcoredumper (0.3-1) unstable; urgency=low 20 | 21 | * Upgraded to version 0.3. 22 | 23 | -- Google Inc. Wed, 14 Feb 2007 14:44:40 -0800 24 | 25 | libcoredumper (0.1-1) unstable; urgency=low 26 | 27 | * Initial release. 28 | 29 | -- Google Inc. Thu, 17 Feb 2005 09:15:32 -0800 30 | -------------------------------------------------------------------------------- /packages/deb/control: -------------------------------------------------------------------------------- 1 | Source: libcoredumper 2 | Priority: optional 3 | Maintainer: Google Inc. 4 | Build-Depends: debhelper (>= 4.0.0), binutils 5 | Standards-Version: 3.6.1 6 | 7 | Package: libcoredumper-dev 8 | Section: libdevel 9 | Architecture: any 10 | Depends: libcoredumper1 (= ${Source-Version}) 11 | Description: library for generating on-the-fly snapshot core files 12 | Libcoredumper can be compiled into applications to create core dumps of 13 | the running program, without having to terminate them. It supports both 14 | single and multi-threaded core dumps, even if the kernel does not have 15 | native support for multi-threaded core files. 16 | 17 | Package: libcoredumper1 18 | Section: libs 19 | Architecture: any 20 | Depends: ${shlibs:Depends} 21 | Description: library for generating on-the-fly snapshot core files 22 | Libcoredumper can be compiled into applications to create core dumps of 23 | the running program, without having to terminate them. It supports both 24 | single and multi-threaded core dumps, even if the kernel does not have 25 | native support for multi-threaded core files. 26 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2005-2007, Google Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /packages/deb/copyright: -------------------------------------------------------------------------------- 1 | This package was debianized by Google Inc. on 2 | 15 February 2007. 3 | 4 | It was downloaded from http://code.google.com/p/google-coredumper/ 5 | 6 | Upstream Author: opensource@google.com 7 | 8 | Copyright (c) 2005-2008, Google Inc. 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are 13 | met: 14 | 15 | * Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | * Redistributions in binary form must reproduce the above 18 | copyright notice, this list of conditions and the following disclaimer 19 | in the documentation and/or other materials provided with the 20 | distribution. 21 | * Neither the name of Google Inc. nor the names of its 22 | contributors may be used to endorse or promote products derived from 23 | this software without specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | ## Process this file with autoconf to produce configure. 2 | ## In general, the safest way to proceed is to run the following: 3 | ## % aclocal -I `pwd`/../autoconf && autoconf && autoheader && automake 4 | 5 | # make sure we're interpreted by some minimal autoconf 6 | AC_PREREQ(2.57) 7 | 8 | AC_INIT(coredumper, 1.2.1, opensource@google.com) 9 | # The argument here is just something that should be in the current directory 10 | # (for sanity checking) 11 | AC_CONFIG_SRCDIR(README) 12 | AM_INIT_AUTOMAKE 13 | AM_CONFIG_HEADER(src/config.h) 14 | 15 | # Checks for programs. 16 | AC_PROG_CC 17 | # This is only needed for linux_syscall_support_unittest, which itself 18 | # only needs c++ for some namespace issues. 19 | AC_PROG_CXX 20 | AC_PROG_INSTALL 21 | 22 | AC_PROG_LIBTOOL 23 | AC_SUBST(LIBTOOL_DEPS) 24 | 25 | # Check whether some low-level functions/files are available 26 | AC_HEADER_STDC 27 | 28 | # Here are some examples of how to check for the existence of a fn or file 29 | AC_CHECK_HEADERS([elf.h errno.h fcntl.h linux/unistd.h pthread.h signal.h \ 30 | stdlib.h string.h sys/prctl.h sys/ptrace.h sys/resource.h \ 31 | sys/socket.h sys/stat.h sys/sysctl.h sys/time.h sys/types.h \ 32 | sys/uio.h sys/wait.h unistd.h]) 33 | 34 | # Checks for typedefs, structures, and compiler characteristics 35 | AC_C_CONST 36 | 37 | # Checks for library functions 38 | AC_PROG_GCC_TRADITIONAL 39 | 40 | # Check if we can force the compiler to generate frame pointers 41 | AC_MSG_CHECKING([whether compiler supports -fno-omit-frame-pointer]) 42 | saved_CFLAGS="$CFLAGS"; CFLAGS="-fno-omit-frame-pointer $CFLAGS" 43 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,)], 44 | [AC_SUBST(AM_CFLAGS, ["$AM_CFLAGS -fno-omit-frame-pointer"]) 45 | AC_MSG_RESULT([yes])], 46 | [AC_MSG_RESULT([no])]) 47 | CFLAGS="$saved_CFLAGS" 48 | 49 | # Write generated configuration file 50 | AC_CONFIG_FILES([Makefile]) 51 | AC_OUTPUT 52 | -------------------------------------------------------------------------------- /src/linuxthreads.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Markus Gutschke 32 | */ 33 | 34 | #ifndef _LINUXTHREADS_H 35 | #define _LINUXTHREADS_H 36 | 37 | /* Include thread_lister.h to get the interface that we implement for linux. 38 | */ 39 | 40 | /* We currently only support x86-32 and x86-64 on Linux. Porting to other 41 | * related platforms should not be difficult. 42 | */ 43 | #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \ 44 | defined(__mips__) || defined(__PPC__)) && defined(__linux) 45 | 46 | /* Define the THREADS symbol to make sure that there is exactly one core dumper 47 | * built into the library. 48 | */ 49 | #define THREADS "Linux /proc" 50 | 51 | #endif 52 | 53 | #endif /* _LINUXTHREADS_H */ 54 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | The coredumper library can be compiled into applications to create 2 | core dumps of the running program, without having to terminate 3 | them. It supports both single- and multi-threaded core dumps, even if 4 | the kernel does not have native support for multi-threaded core files. 5 | 6 | This library is primarily intended to simplify debugging of 7 | long-running services. It is often inacceptable to suspend production 8 | services by attaching a debugger, nor is it possible to crash the 9 | service in order to generate a core file. 10 | 11 | By modifying an existing service to take advantage of the coredumper 12 | library, it is possible to expose an interface for obtaining snapshots 13 | of the running application. The library supports writing of core files 14 | to disk (e.g. triggered upon reception of a signal) but it can also 15 | generate in-memory core files. This makes it possible for web 16 | services to expose remote access to core files. 17 | 18 | The "examples" directory shows how to add a core file feature to an 19 | existing TFTP server. For an example of how to use on-disk core files, 20 | take a look at "src/coredump_unittest.c". 21 | 22 | The code has been tested on Linux x86/32, x86/64, and ARM. It is 23 | distributed from http://code.google.com/p/google-coredumper. It is 24 | available as a tar source archive, and in prebuilt form as Debian and 25 | RedHat packages. 26 | 27 | For detailed information on how to build and install this library, 28 | read the "INSTALL" file. On most systems, you will need to configure 29 | and build by running: 30 | 31 | ./configure && make 32 | 33 | You can then test whether the code works correctly on your system, by 34 | running: 35 | 36 | make check 37 | 38 | The check requires that you have access to development tools such as 39 | "readelf", and "gdb". 40 | 41 | If you decide to install from the tar file, you now need to run the 42 | following command as "root": 43 | 44 | make install 45 | 46 | Alternatively, you can build packages for your targeted distribution 47 | by running either: 48 | 49 | make deb 50 | or 51 | make rpm 52 | 53 | These commands generate installable package files. The packages will 54 | be located in the "packages/" directory (e. g. packages/rh9 55 | or packages/woody). The exact path name is printed at the end of the 56 | compilation. 57 | 58 | Follow your distribution's instructions on how to install new 59 | packages. 60 | 61 | For more information on how to use the library, read the manual pages 62 | for "GetCoreDump" and "WriteCoreDump". 63 | 64 | 15 February 2007 65 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | # This makefile will probably work out of the box for you, but if not, try 2 | # changing PTHREAD to be -pthread (possibly needed for FreeBSD), and/or CC 3 | # to be cc (possibly needed for Solaris). 4 | 5 | PORT = 9900 6 | LIBTOOL = ../libtool 7 | CC = gcc 8 | PTHREAD = -lpthread 9 | 10 | all: tftpd 11 | 12 | # This rule works both in the source tree, and stand-alone. In the latter case 13 | # it assumes that the libraries and headers are installed system-wide. 14 | tftpd: tftpd.c 15 | @if [ -r ../src/coredumper.c ]; then \ 16 | ( cd .. && { [ -r Makefile ] || ./configure; } && $(MAKE) ) &&\ 17 | echo $(CC) -o $@ -g -Wall -O2 -lcoredumper $(PTHREAD) \ 18 | tftpd.c && \ 19 | $(LIBTOOL) --mode=link $(CC) -o $@ -g -Wall -O2 -I../src -L.. \ 20 | -lcoredumper $(PTHREAD) $^ ../libcoredumper.la; \ 21 | else \ 22 | echo $(CC) -o $@ -g -Wall -O2 -lcoredumper $(PTHREAD) tftpd.c;\ 23 | $(CC) -o $@ -g -Wall -O2 -lcoredumper $(PTHREAD) tftpd.c; \ 24 | fi 25 | 26 | distclean: clean 27 | clean: 28 | @echo $(RM) -f tftpd core 29 | @if [ -r ../src/coredumper.c ]; then \ 30 | $(LIBTOOL) --mode=clean $(RM) -f tftpd core; \ 31 | else \ 32 | $(RM) -f tftpd core; \ 33 | fi 34 | 35 | check: tftpd 36 | @echo "Starting TFTP server on port $(PORT)" && \ 37 | rm -f core && set -m && \ 38 | { ./tftpd --port $(PORT) /dev/null 2>&1" EXIT && \ 40 | sleep 1 && \ 41 | echo "Downloading tftp://localhost:$(PORT)/core" && \ 42 | { echo; \ 43 | echo "connect localhost $(PORT)"; \ 44 | echo "binary"; \ 45 | echo "get core"; \ 46 | echo "quit"; } | tftp >/dev/null && \ 47 | kill -15 -$$pid >/dev/null 2>&1 && \ 48 | { wait $$pid; [ $$? -eq 143 ]; } && \ 49 | echo "Validating core file contents" && \ 50 | readelf -a core && \ 51 | echo "PASS" || \ 52 | echo "FAILED" 53 | -------------------------------------------------------------------------------- /packages/rpm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # Run this from the 'packages' directory, just under rootdir 4 | 5 | # We can only build rpm packages, if the rpm build tools are installed 6 | if [ \! -x /usr/bin/rpmbuild ] 7 | then 8 | echo "Cannot find /usr/bin/rpmbuild. Not building an rpm." 1>&2 9 | exit 0 10 | fi 11 | 12 | # Check the commandline flags 13 | PACKAGE="$1" 14 | VERSION="$2" 15 | fullname="${PACKAGE}-${VERSION}" 16 | archive=../$fullname.tar.gz 17 | 18 | if [ -z "$1" -o -z "$2" ] 19 | then 20 | echo "Usage: $0 " 1>&2 21 | exit 0 22 | fi 23 | 24 | # Double-check we're in the packages directory, just under rootdir 25 | if [ \! -r ../Makefile -a \! -r ../INSTALL ] 26 | then 27 | echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2 28 | echo "Also, you must run \"make dist\" before running this script." 1>&2 29 | exit 0 30 | fi 31 | 32 | if [ \! -r "$archive" ] 33 | then 34 | echo "Cannot find $archive. Run \"make dist\" first." 1>&2 35 | exit 0 36 | fi 37 | 38 | # Create the directory where the input lives, and where the output should live 39 | RPM_SOURCE_DIR="/tmp/rpmsource-$fullname" 40 | RPM_BUILD_DIR="/tmp/rpmbuild-$fullname" 41 | 42 | trap 'rm -rf $RPM_SOURCE_DIR $RPM_BUILD_DIR; exit $?' EXIT SIGHUP SIGINT SIGTERM 43 | 44 | rm -rf "$RPM_SOURCE_DIR" "$RPM_BUILD_DIR" 45 | mkdir "$RPM_SOURCE_DIR" 46 | mkdir "$RPM_BUILD_DIR" 47 | 48 | cp "$archive" "$RPM_SOURCE_DIR" 49 | 50 | rpmbuild -bb rpm/rpm.spec \ 51 | --define "NAME $PACKAGE" \ 52 | --define "VERSION $VERSION" \ 53 | --define "_sourcedir $RPM_SOURCE_DIR" \ 54 | --define "_builddir $RPM_BUILD_DIR" \ 55 | --define "_rpmdir $RPM_SOURCE_DIR" 56 | 57 | # We put the output in a directory based on what system we've built for 58 | destdir=rpm-unknown 59 | if [ -r /etc/issue ] 60 | then 61 | grep "Red Hat.*release 7" /etc/issue >/dev/null 2>&1 && destdir=rh7 62 | grep "Red Hat.*release 8" /etc/issue >/dev/null 2>&1 && destdir=rh8 63 | grep "Red Hat.*release 9" /etc/issue >/dev/null 2>&1 && destdir=rh9 64 | grep "Fedora Core.*release 1" /etc/issue >/dev/null 2>&1 && destdir=fc1 65 | grep "Fedora Core.*release 2" /etc/issue >/dev/null 2>&1 && destdir=fc2 66 | grep "Fedora Core.*release 3" /etc/issue >/dev/null 2>&1 && destdir=fc3 67 | grep "Fedora Core.*release 4" /etc/issue >/dev/null 2>&1 && destdir=fc4 68 | grep "Fedora Core.*release 5" /etc/issue >/dev/null 2>&1 && destdir=fc5 69 | grep "Fedora Core.*release 6" /etc/issue >/dev/null 2>&1 && destdir=fc6 70 | fi 71 | 72 | rm -rf "$destdir" 73 | mkdir -p "$destdir" 74 | # We want to get not only the main package but devel etc, hence the middle * 75 | mv "$RPM_SOURCE_DIR"/*/"${PACKAGE}"-*"${VERSION}"*.rpm "$destdir" 76 | 77 | echo 78 | echo "The rpm package file(s) are located in $PWD/$destdir" 79 | -------------------------------------------------------------------------------- /src/thread_lister.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Markus Gutschke 32 | */ 33 | 34 | #include /* needed for NULL on some powerpc platforms (?!) */ 35 | #include 36 | #include "thread_lister.h" 37 | #include "linuxthreads.h" 38 | /* Include other thread listers here that define THREADS macro 39 | * only when they can provide a good implementation. 40 | */ 41 | 42 | #ifndef THREADS 43 | 44 | /* Default trivial thread lister for single-threaded applications, 45 | * or if the multi-threading code has not been ported, yet. 46 | */ 47 | 48 | int ListAllProcessThreads(void *parameter, 49 | ListAllProcessThreadsCallBack callback, ...) { 50 | int rc; 51 | va_list ap; 52 | 53 | int dumpable = prctl(PR_GET_DUMPABLE, 0); 54 | if (!dumpable) 55 | prctl(PR_SET_DUMPABLE, 1); 56 | va_start(ap, callback); 57 | pid_t pid = getpid(); 58 | rc = callback(parameter, 1, &pid, ap); 59 | va_end(ap); 60 | if (!dumpable) 61 | prctl(PR_SET_DUMPABLE, 0); 62 | return rc; 63 | } 64 | 65 | int ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) { 66 | return 1; 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /packages/rpm/rpm.spec: -------------------------------------------------------------------------------- 1 | %define ver %VERSION 2 | %define RELEASE 1 3 | %define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE} 4 | %define prefix /usr 5 | 6 | Name: %NAME 7 | Summary: Generate a core dump of a running program without crashing 8 | Version: %ver 9 | Release: %rel 10 | Group: Development/Libraries 11 | URL: http://code.google.com/p/google-coredumper 12 | License: BSD 13 | Vendor: Google 14 | Packager: Google 15 | Source: http://google-coredumper.googlecode.com/files/%{NAME}-%{PACKAGE_VERSION}.tar.gz 16 | Distribution: Redhat 7 and above. 17 | Buildroot: %{_tmppath}/%{name}-root 18 | Prefix: %prefix 19 | 20 | %description 21 | The %name utility allows a running program to generate a core 22 | file without actually crashing. This serves to allow the programmer 23 | to generate a snapshot of a running program's state at any time. 24 | 25 | %package devel 26 | Summary: Generate a core dump of a running program without crashing 27 | Group: Development/Libraries 28 | Requires: %{name} = %{version} 29 | 30 | %description devel 31 | The %name-devel package contains static and debug libraries and header 32 | files for developing applications that use the %name utility. 33 | 34 | %changelog 35 | * Thu Mar 3 2008 36 | - Updated for version 1.2 37 | 38 | * Thu Feb 15 2007 39 | - Added dependencies to devel RPMs 40 | - Added manual pages 41 | 42 | * Wed Feb 14 2007 43 | - Fixed compatibility with new RPM versions 44 | 45 | * Fri Feb 11 2005 46 | - First draft 47 | 48 | %prep 49 | %setup 50 | 51 | %build 52 | ./configure 53 | make prefix=%prefix 54 | 55 | %install 56 | rm -rf $RPM_BUILD_ROOT 57 | make prefix=$RPM_BUILD_ROOT%{prefix} install 58 | 59 | %clean 60 | rm -rf $RPM_BUILD_ROOT 61 | 62 | %files 63 | %defattr(-,root,root) 64 | 65 | %doc AUTHORS COPYING ChangeLog INSTALL NEWS README TODO examples 66 | 67 | %{prefix}/lib/libcoredumper.so.1 68 | %{prefix}/lib/libcoredumper.so.1.0.0 69 | 70 | 71 | %files devel 72 | %defattr(-,root,root) 73 | 74 | %{prefix}/include/google 75 | %{prefix}/lib/libcoredumper.a 76 | %{prefix}/lib/libcoredumper.la 77 | %{prefix}/lib/libcoredumper.so 78 | %{prefix}/man/man3/ClearCoreDumpParameters.3.gz 79 | %{prefix}/man/man3/CoreDumpParameters.3.gz 80 | %{prefix}/man/man3/GetCompressedCoreDump.3.gz 81 | %{prefix}/man/man3/GetCoreDump.3.gz 82 | %{prefix}/man/man3/GetCoreDumpWith.3.gz 83 | %{prefix}/man/man3/SetCoreDumpCompressed.3.gz 84 | %{prefix}/man/man3/SetCoreDumpLimited.3.gz 85 | %{prefix}/man/man3/SetCoreDumpLimitedByPriority.3.gz 86 | %{prefix}/man/man3/SetCoreDumpNotes.3.gz 87 | %{prefix}/man/man3/WriteCompressedCoreDump.3.gz 88 | %{prefix}/man/man3/WriteCoreDump.3.gz 89 | %{prefix}/man/man3/WriteCoreDumpLimited.3.gz 90 | %{prefix}/man/man3/WriteCoreDumpLimitedByPriority.3.gz 91 | %{prefix}/man/man3/WriteCoreDumpWith.3.gz 92 | %{prefix}/man/man3/WriteCoreDumpWith.3.gz 93 | 94 | -------------------------------------------------------------------------------- /packages/deb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # This takes one commandline argument, the name of the package. If no 4 | # name is given, then we'll end up just using the name associated with 5 | # an arbitrary .tar.gz file in the rootdir. That's fine: there's probably 6 | # only one. 7 | # 8 | # Run this from the 'packages' directory, just under rootdir 9 | 10 | ## Set LIB to lib if exporting a library, empty-string else 11 | LIB= 12 | #LIB=lib 13 | 14 | PACKAGE="$1" 15 | 16 | # We can only build Debian packages, if the Debian build tools are installed 17 | if [ \! -x /usr/bin/debuild ]; then 18 | echo "Cannot find /usr/bin/debuild. Not building Debian packages." 1>&2 19 | exit 0 20 | fi 21 | 22 | # Double-check we're in the packages directory, just under rootdir 23 | if [ \! -r ../Makefile -a \! -r ../INSTALL ]; then 24 | echo "Must run $0 in the 'packages' directory, under the root directory." 1>&2 25 | echo "Also, you must run \"make dist\" before running this script." 1>&2 26 | exit 0 27 | fi 28 | 29 | # Find the top directory for this package 30 | topdir="${PWD%/*}" 31 | 32 | # Find the tar archive built by "make dist" 33 | archive="$(basename "$(ls -1 ${topdir}/$PACKAGE*.tar.gz | tail -n 1)" .tar.gz)" 34 | if [ -z "${archive}" ]; then 35 | echo "Cannot find ../$PACKAGE*.tar.gz. Run \"make dist\" first." 1>&2 36 | exit 0 37 | fi 38 | 39 | # Create a pristine directory for building the Debian package files 40 | trap 'rm -rf '`pwd`/tmp'; exit $?' EXIT SIGHUP SIGINT SIGTERM 41 | 42 | rm -rf tmp 43 | mkdir -p tmp 44 | cd tmp 45 | 46 | # Debian has very specific requirements about the naming of build 47 | # directories, and tar archives. It also wants to write all generated 48 | # packages to the parent of the source directory. We accommodate these 49 | # requirements by building directly from the tar file. 50 | ln -s "${topdir}/${archive}.tar.gz" "${LIB}${archive}.orig.tar.gz" 51 | tar zfx "${LIB}${archive}.orig.tar.gz" 52 | [ -n "${LIB}" ] && mv "${archive}" "${LIB}${archive}" 53 | cd "${LIB}${archive}" 54 | # This is one of those 'specific requirements': where the deb control files live 55 | ln -s "packages/deb" "debian" 56 | 57 | # Now, we can call Debian's standard build tool 58 | debuild -uc -us 59 | cd ../.. # get back to the original top-level dir 60 | 61 | # We'll put the result in a subdirectory that's named after the OS version 62 | # we've made this .deb file for. 63 | if [ -r /etc/lsb-release ]; then 64 | # Try looking in lsb-release first, as it tends to have the actual code name 65 | . /etc/lsb-release 66 | [ -n "$DISTRIB_CODENAME" ] && destdir="debian-$DISTRIB_CODENAME" 67 | [ -z "$destdir" -a -n "$DISTRIB_TRACK" ] && destdir="debian-$DISTRIB_TRACK" 68 | fi 69 | if [ -z "$destdir" ]; then 70 | # If lsb-release did not have any useful data, fall back on debian_version 71 | track="$(cat /etc/debian_version 2>/dev/null)" 72 | track="${track#*/}" 73 | destdir="debian-${track:-unknown}" 74 | fi 75 | 76 | rm -rf "$destdir" 77 | mkdir -p "$destdir" 78 | mv $(find tmp -mindepth 1 -maxdepth 1 -type f) "$destdir" 79 | 80 | echo 81 | echo "The Debian package files are located in $PWD/$destdir" 82 | -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | /* src/config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file. */ 4 | #undef HAVE_DLFCN_H 5 | 6 | /* Define to 1 if you have the header file. */ 7 | #undef HAVE_ELF_H 8 | 9 | /* Define to 1 if you have the header file. */ 10 | #undef HAVE_ERRNO_H 11 | 12 | /* Define to 1 if you have the header file. */ 13 | #undef HAVE_FCNTL_H 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_INTTYPES_H 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #undef HAVE_LINUX_UNISTD_H 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_MEMORY_H 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_PTHREAD_H 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #undef HAVE_SIGNAL_H 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #undef HAVE_STDINT_H 32 | 33 | /* Define to 1 if you have the header file. */ 34 | #undef HAVE_STDLIB_H 35 | 36 | /* Define to 1 if you have the header file. */ 37 | #undef HAVE_STRINGS_H 38 | 39 | /* Define to 1 if you have the header file. */ 40 | #undef HAVE_STRING_H 41 | 42 | /* Define to 1 if you have the header file. */ 43 | #undef HAVE_SYS_PRCTL_H 44 | 45 | /* Define to 1 if you have the header file. */ 46 | #undef HAVE_SYS_PTRACE_H 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #undef HAVE_SYS_RESOURCE_H 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #undef HAVE_SYS_SOCKET_H 53 | 54 | /* Define to 1 if you have the header file. */ 55 | #undef HAVE_SYS_STAT_H 56 | 57 | /* Define to 1 if you have the header file. */ 58 | #undef HAVE_SYS_SYSCTL_H 59 | 60 | /* Define to 1 if you have the header file. */ 61 | #undef HAVE_SYS_TIME_H 62 | 63 | /* Define to 1 if you have the header file. */ 64 | #undef HAVE_SYS_TYPES_H 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #undef HAVE_SYS_UIO_H 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #undef HAVE_SYS_WAIT_H 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #undef HAVE_UNISTD_H 74 | 75 | /* Name of package */ 76 | #undef PACKAGE 77 | 78 | /* Define to the address where bug reports for this package should be sent. */ 79 | #undef PACKAGE_BUGREPORT 80 | 81 | /* Define to the full name of this package. */ 82 | #undef PACKAGE_NAME 83 | 84 | /* Define to the full name and version of this package. */ 85 | #undef PACKAGE_STRING 86 | 87 | /* Define to the one symbol short name of this package. */ 88 | #undef PACKAGE_TARNAME 89 | 90 | /* Define to the version of this package. */ 91 | #undef PACKAGE_VERSION 92 | 93 | /* Define to 1 if you have the ANSI C header files. */ 94 | #undef STDC_HEADERS 95 | 96 | /* Version number of package */ 97 | #undef VERSION 98 | 99 | /* Define to empty if `const' does not conform to ANSI C. */ 100 | #undef const 101 | -------------------------------------------------------------------------------- /compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Wrapper for compilers which do not understand `-c -o'. 4 | 5 | # Copyright 1999, 2000 Free Software Foundation, Inc. 6 | # Written by Tom Tromey . 7 | # 8 | # This program is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2, or (at your option) 11 | # any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program; if not, write to the Free Software 20 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | # Usage: 28 | # compile PROGRAM [ARGS]... 29 | # `-o FOO.o' is removed from the args passed to the actual compile. 30 | 31 | prog=$1 32 | shift 33 | 34 | ofile= 35 | cfile= 36 | args= 37 | while test $# -gt 0; do 38 | case "$1" in 39 | -o) 40 | # configure might choose to run compile as `compile cc -o foo foo.c'. 41 | # So we do something ugly here. 42 | ofile=$2 43 | shift 44 | case "$ofile" in 45 | *.o | *.obj) 46 | ;; 47 | *) 48 | args="$args -o $ofile" 49 | ofile= 50 | ;; 51 | esac 52 | ;; 53 | *.c) 54 | cfile=$1 55 | args="$args $1" 56 | ;; 57 | *) 58 | args="$args $1" 59 | ;; 60 | esac 61 | shift 62 | done 63 | 64 | if test -z "$ofile" || test -z "$cfile"; then 65 | # If no `-o' option was seen then we might have been invoked from a 66 | # pattern rule where we don't need one. That is ok -- this is a 67 | # normal compilation that the losing compiler can handle. If no 68 | # `.c' file was seen then we are probably linking. That is also 69 | # ok. 70 | exec "$prog" $args 71 | fi 72 | 73 | # Name of file we expect compiler to create. 74 | cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'` 75 | 76 | # Create the lock directory. 77 | # Note: use `[/.-]' here to ensure that we don't use the same name 78 | # that we are using for the .o file. Also, base the name on the expected 79 | # object file name, since that is what matters with a parallel build. 80 | lockdir=`echo $cofile | sed -e 's|[/.-]|_|g'`.d 81 | while true; do 82 | if mkdir $lockdir > /dev/null 2>&1; then 83 | break 84 | fi 85 | sleep 1 86 | done 87 | # FIXME: race condition here if user kills between mkdir and trap. 88 | trap "rmdir $lockdir; exit 1" 1 2 15 89 | 90 | # Run the compile. 91 | "$prog" $args 92 | status=$? 93 | 94 | if test -f "$cofile"; then 95 | mv "$cofile" "$ofile" 96 | fi 97 | 98 | rmdir $lockdir 99 | exit $status 100 | -------------------------------------------------------------------------------- /packages/deb/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # This file was originally written by Joey Hess and Craig Small. 5 | # As a special exception, when this file is copied by dh-make into a 6 | # dh-make output file, you may use that output file without restriction. 7 | # This special exception was added by Craig Small in version 0.37 of dh-make. 8 | 9 | # Uncomment this to turn on verbose mode. 10 | #export DH_VERBOSE=1 11 | 12 | 13 | # These are used for cross-compiling and for saving the configure script 14 | # from having to guess our platform (since we know it already) 15 | DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) 16 | DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) 17 | 18 | 19 | CFLAGS = -Wall -g 20 | 21 | ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) 22 | CFLAGS += -O0 23 | else 24 | CFLAGS += -O2 25 | endif 26 | ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) 27 | INSTALL_PROGRAM += -s 28 | endif 29 | 30 | # shared library versions, option 1 31 | #version=2.0.5 32 | #major=2 33 | # option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so 34 | version=`ls src/.libs/lib*.so.* | \ 35 | awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'` 36 | major=`ls src/.libs/lib*.so.* | \ 37 | awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'` 38 | 39 | config.status: configure 40 | dh_testdir 41 | # Add here commands to configure the package. 42 | CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info 43 | 44 | 45 | build: build-stamp 46 | build-stamp: config.status 47 | dh_testdir 48 | 49 | # Add here commands to compile the package. 50 | $(MAKE) 51 | 52 | touch build-stamp 53 | 54 | clean: 55 | dh_testdir 56 | dh_testroot 57 | rm -f build-stamp 58 | 59 | # Add here commands to clean up after the build process. 60 | -$(MAKE) distclean 61 | ifneq "$(wildcard /usr/share/misc/config.sub)" "" 62 | cp -f /usr/share/misc/config.sub config.sub 63 | endif 64 | ifneq "$(wildcard /usr/share/misc/config.guess)" "" 65 | cp -f /usr/share/misc/config.guess config.guess 66 | endif 67 | 68 | 69 | dh_clean 70 | 71 | install: build 72 | dh_testdir 73 | dh_testroot 74 | dh_clean -k 75 | dh_installdirs 76 | 77 | # Add here commands to install the package into debian/tmp 78 | $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp 79 | 80 | 81 | # Build architecture-independent files here. 82 | binary-indep: build install 83 | # We have nothing to do by default. 84 | 85 | # Build architecture-dependent files here. 86 | binary-arch: build install 87 | dh_testdir 88 | dh_testroot 89 | dh_installchangelogs ChangeLog 90 | dh_installdocs 91 | dh_installexamples 92 | dh_install --sourcedir=debian/tmp 93 | # dh_installmenu 94 | # dh_installdebconf 95 | # dh_installlogrotate 96 | # dh_installemacsen 97 | # dh_installpam 98 | # dh_installmime 99 | # dh_installinit 100 | # dh_installcron 101 | # dh_installinfo 102 | dh_installman 103 | dh_link 104 | dh_strip 105 | dh_compress 106 | dh_fixperms 107 | # dh_perl 108 | # dh_python 109 | dh_makeshlibs 110 | dh_installdeb 111 | dh_shlibdeps 112 | dh_gencontrol 113 | dh_md5sums 114 | dh_builddeb 115 | 116 | binary: binary-indep binary-arch 117 | .PHONY: build clean binary-indep binary-arch binary install 118 | -------------------------------------------------------------------------------- /src/thread_lister.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2007, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Markus Gutschke 32 | */ 33 | 34 | #ifndef _THREAD_LISTER_H 35 | #define _THREAD_LISTER_H 36 | 37 | #include 38 | #include 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | typedef int (*ListAllProcessThreadsCallBack)(void *parameter, 45 | int num_threads, 46 | pid_t *thread_pids, 47 | va_list ap); 48 | 49 | /* This function gets the list of all linux threads of the current process 50 | * passes them to the 'callback' along with the 'parameter' pointer; at the 51 | * call back call time all the threads are paused via 52 | * PTRACE_ATTACH. 53 | * The callback is executed from a separate thread which shares only the 54 | * address space, the filesystem, and the filehandles with the caller. Most 55 | * notably, it does not share the same pid and ppid; and if it terminates, 56 | * the rest of the application is still there. 'callback' is supposed to do 57 | * or arrange for ResumeAllProcessThreads. This happens automatically, if 58 | * the thread raises a synchronous signal (e.g. SIGSEGV); asynchronous 59 | * signals are blocked. If the 'callback' decides to unblock them, it must 60 | * ensure that they cannot terminate the application, or that 61 | * ResumeAllProcessThreads will get called. 62 | * It is an error for the 'callback' to make any library calls that could 63 | * acquire locks. Most notably, this means that most system calls have to 64 | * avoid going through libc. Also, this means that it is not legal to call 65 | * exit() or abort(). 66 | * We return -1 on error and the return value of 'callback' on success. 67 | */ 68 | int ListAllProcessThreads(void *parameter, 69 | ListAllProcessThreadsCallBack callback, ...); 70 | 71 | /* This function resumes the list of all linux threads that 72 | * ListAllProcessThreads pauses before giving to its callback. 73 | * The function returns non-zero if at least one thread was 74 | * suspended and has now been resumed. 75 | */ 76 | int ResumeAllProcessThreads(int num_threads, pid_t *thread_pids); 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | 82 | #endif /* _THREAD_LISTER_H */ 83 | -------------------------------------------------------------------------------- /man/CoreDumpParameters.man: -------------------------------------------------------------------------------- 1 | '\" t 2 | .TH COREDUMPERPARAMETERS 3 "Mar 11, 2008" 3 | .SH NAME 4 | ClearCoreDumpParameters, SetCoreDumpLimited, SetCoreDumpCompressed, SetCoreDumpLimitedByPriority, SetCoreDumpNotes \- functions to initialize and set fields in a CoreDumpParameters structure. 5 | .SH SYNOPSIS 6 | .ad l 7 | .PP 8 | .B "#include \*(lqgoogle/coredumper.h\*(rq" 9 | .HP 30 10 | .BI void\~Clear\%Core\%Dump\%Parameters(struct\~CoreDump\%Parameters\ \:* params ); 11 | .HP 23 12 | .BI int\~Set\%Core\%Dump\%Limited(\:struct\~Core\%Dump\%Parameters\ \:* params ,\ size_t\~ \:max_length ); 13 | .HP 33 14 | .BI int\~Set\%Core\%Dump\%Limited\%By\%Priority(\:struct\~Core\%Dump\%Parameters\ \:* params ,\ size_t\ \: max_length ); 15 | .HP 26 16 | .BI int\~Set\%Core\%Dump\%Compressed(\:struct\~Core\%Dump\%Parameters\ * \:params ,\ const\~struct\~Coredump\%Compressor\ \:* compressors\ 17 | ,\ \:struct\~Coredumper\%Compressor\ \:** \ 18 | selected_compressor ); 19 | .HP 21 20 | .BI int\~Set\%Core\%Dump\%Notes(\:struct\~Core\%Dump\%Parameters\ \:* params ,\ \:struct\~Coredumper\%Note\~\:* notes ,\ \:int\~ \:note_count ); 21 | .ad b 22 | .SH DESCRIPTION 23 | These functions must be used to set the attributes in a CoreDumpParameters 24 | structure. Combinations of these functions may be used together. For instance 25 | to produce a compressed core dump with additional notes you should call 26 | \fBClearCoreDumpParameters\fP(), \fBSetCoreDumpCompressed\fP() and 27 | \fBSetCoreDumpNotes\fP(). 28 | .PP 29 | The \fBClearCoreDumpParameters\fP() function clears the given 30 | core dumper parameters structure to its default values. 31 | .PP 32 | The \fBSetCoreDumpLimited\fP() function sets the attributes in 33 | .IR params 34 | to produce core files of at most 35 | .IR max_length 36 | bytes when called with \fBWriteCoreDumpWith\fP(). This must not be used with 37 | \fBSetCoreDumpLimitedByPriority\fP(). 38 | .PP 39 | The \fBSetCoreDumpLimitedByPriority\fP() function sets the attributes in 40 | .IR params 41 | to produce core files of at most 42 | .IR max_length 43 | bytes when called with \fBWriteCoreDumpWith\fP(). This differs from normal 44 | limiting by truncating the largest memory segments first as opposed to 45 | truncating the whole core file. This must not be used with 46 | \fBSetCoreDumpLimited\fP() or \fBSetCoreDumpCompressed\fP(). 47 | .PP 48 | The \fBSetCoreDumpCompressed\fP() function sets the attributes in 49 | .IR params 50 | to produce a compressed core dump when called with \fBGetCoreDumpWith\fP() or 51 | \fBWriteCoreDumpWith\fP(). Its arguments match the ones passed to 52 | \fBGetCompressedCoreDump\fP(). 53 | .PP 54 | The \fBSetCoreDumpNotes\fP() function sets the attributes in 55 | .IR params 56 | to add additional notes to core dumps when called with \fBGetCoreDumpWith\fP() 57 | or \fBWriteCoreDumpWith\fP(). The notes are specified as an array of the 58 | CoredumperNote structure: 59 | .sp 60 | .RS 61 | .nf 62 | struct CoredumperNote { 63 | const char *name; // The vendor name 64 | unsigned int type; // A vendor specific type 65 | unsigned int description_size; // The size of the description field 66 | const void *description; // The note data 67 | }; 68 | .fi 69 | .RE 70 | .PP 71 | The name, including a terminating null character, will be 4 byte aligned. The 72 | type is a user chosen value. The description_size specifies the amount of bytes 73 | to write from the description pointer in memory to the core dump note. The 74 | description will be padded to be 4 byte aligned. 75 | .PP 76 | .SH RETURN VALUE 77 | .PP 78 | On success 0 will be returned. On error \-1 will be returned and 79 | .I errno 80 | will be set appropriately. 81 | .SH ERRORS 82 | The most common reason for an error is that incompatable parameters are combined. 83 | .SH "SEE ALSO" 84 | .BR GetCoreDump (3), 85 | .BR GetCoreDumpWith (3), 86 | .BR GetCompressedCoreDump(3), 87 | .BR WriteCoreDump (3), 88 | .BR WriteCoreDumpWith (3), 89 | .BR WriteCoreDumpLimited (3), 90 | .BR WriteCoreDumpLimitedByPriority (3), 91 | and 92 | .BR WriteCompressedCoreDump(3). 93 | -------------------------------------------------------------------------------- /mkinstalldirs: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # mkinstalldirs --- make directory hierarchy 3 | 4 | scriptversion=2005-06-29.22 5 | 6 | # Original author: Noah Friedman 7 | # Created: 1993-05-16 8 | # Public domain. 9 | # 10 | # This file is maintained in Automake, please report 11 | # bugs to or send patches to 12 | # . 13 | 14 | errstatus=0 15 | dirmode= 16 | 17 | usage="\ 18 | Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... 19 | 20 | Create each directory DIR (with mode MODE, if specified), including all 21 | leading file name components. 22 | 23 | Report bugs to ." 24 | 25 | # process command line arguments 26 | while test $# -gt 0 ; do 27 | case $1 in 28 | -h | --help | --h*) # -h for help 29 | echo "$usage" 30 | exit $? 31 | ;; 32 | -m) # -m PERM arg 33 | shift 34 | test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } 35 | dirmode=$1 36 | shift 37 | ;; 38 | --version) 39 | echo "$0 $scriptversion" 40 | exit $? 41 | ;; 42 | --) # stop option processing 43 | shift 44 | break 45 | ;; 46 | -*) # unknown option 47 | echo "$usage" 1>&2 48 | exit 1 49 | ;; 50 | *) # first non-opt arg 51 | break 52 | ;; 53 | esac 54 | done 55 | 56 | for file 57 | do 58 | if test -d "$file"; then 59 | shift 60 | else 61 | break 62 | fi 63 | done 64 | 65 | case $# in 66 | 0) exit 0 ;; 67 | esac 68 | 69 | # Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and 70 | # mkdir -p a/c at the same time, both will detect that a is missing, 71 | # one will create a, then the other will try to create a and die with 72 | # a "File exists" error. This is a problem when calling mkinstalldirs 73 | # from a parallel make. We use --version in the probe to restrict 74 | # ourselves to GNU mkdir, which is thread-safe. 75 | case $dirmode in 76 | '') 77 | if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then 78 | echo "mkdir -p -- $*" 79 | exec mkdir -p -- "$@" 80 | else 81 | # On NextStep and OpenStep, the `mkdir' command does not 82 | # recognize any option. It will interpret all options as 83 | # directories to create, and then abort because `.' already 84 | # exists. 85 | test -d ./-p && rmdir ./-p 86 | test -d ./--version && rmdir ./--version 87 | fi 88 | ;; 89 | *) 90 | if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && 91 | test ! -d ./--version; then 92 | echo "mkdir -m $dirmode -p -- $*" 93 | exec mkdir -m "$dirmode" -p -- "$@" 94 | else 95 | # Clean up after NextStep and OpenStep mkdir. 96 | for d in ./-m ./-p ./--version "./$dirmode"; 97 | do 98 | test -d $d && rmdir $d 99 | done 100 | fi 101 | ;; 102 | esac 103 | 104 | for file 105 | do 106 | case $file in 107 | /*) pathcomp=/ ;; 108 | *) pathcomp= ;; 109 | esac 110 | oIFS=$IFS 111 | IFS=/ 112 | set fnord $file 113 | shift 114 | IFS=$oIFS 115 | 116 | for d 117 | do 118 | test "x$d" = x && continue 119 | 120 | pathcomp=$pathcomp$d 121 | case $pathcomp in 122 | -*) pathcomp=./$pathcomp ;; 123 | esac 124 | 125 | if test ! -d "$pathcomp"; then 126 | echo "mkdir $pathcomp" 127 | 128 | mkdir "$pathcomp" || lasterr=$? 129 | 130 | if test ! -d "$pathcomp"; then 131 | errstatus=$lasterr 132 | else 133 | if test ! -z "$dirmode"; then 134 | echo "chmod $dirmode $pathcomp" 135 | lasterr= 136 | chmod "$dirmode" "$pathcomp" || lasterr=$? 137 | 138 | if test ! -z "$lasterr"; then 139 | errstatus=$lasterr 140 | fi 141 | fi 142 | fi 143 | fi 144 | 145 | pathcomp=$pathcomp/ 146 | done 147 | done 148 | 149 | exit $errstatus 150 | 151 | # Local Variables: 152 | # mode: shell-script 153 | # sh-indentation: 2 154 | # eval: (add-hook 'write-file-hooks 'time-stamp) 155 | # time-stamp-start: "scriptversion=" 156 | # time-stamp-format: "%:y-%02m-%02d.%02H" 157 | # time-stamp-end: "$" 158 | # End: 159 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | Fri Feb 11 12:51:37 2005 Google Inc. 2 | 3 | * coredumper: initial release: 4 | The coredumper utility allows a running program to generate a 5 | core file without actually crashing. This serves to allow the 6 | programmer to generate a snapshot of a running program's state 7 | at any time. 8 | 9 | Mon May 2 07:04:46 2005 Google Inc. 10 | 11 | * coredumper: version 0.2 release 12 | * fixed compilation on icc (simonb) 13 | * added a new WriteCoreDumpLimited() function that allows the 14 | caller to specify the maximum core file size. This is needed to 15 | emulate "ulimit -c". (markus) 16 | 17 | Thu Aug 10 12:44:40 2006 Google Inc. 18 | 19 | * coredumper: version 0.3 release 20 | * reorganized the source to make porting and reuse easier. 21 | * ported to ARM. 22 | * core files can now be compressed on-the-fly. 23 | * added support for recent 2.6.x kernels, which subtly changed the 24 | ptrace() API. It used to be possible to PTRACE_ATTACH to threads 25 | in the same process, but newer kernels require making this call 26 | from a separate process. This change is backwards compatible. 27 | * improved compatibility with more (historic) versions of both 28 | libc and of the Linux kernel. 29 | * the convenience methods now enforce more restrictive file 30 | permissions when writing to disk. The caller no longer needs to 31 | adjust the umask() to make file writing secure. 32 | * the coredumper fails gracefully if called when the stack is almost 33 | about to overflow. 34 | * fixed bugs that prevented thread listing on 64bit machines. 35 | * switched to different syscall() functions in order to better 36 | preserve the call stack. Added work-around for broken libc 37 | system headers. 38 | * all assembly code is position-independent. 39 | * the unittest can now be run even if the systems locale is not 40 | English. 41 | 42 | Wed Feb 14 14:44:40 2007 Google Inc. 43 | 44 | * fixed some packaging problems with newer versions of RPM 45 | * added assembly version of sys_clone() in order to work around 46 | buggy implementations in glibc. 47 | 48 | Thu Feb 15 16:24:32 2007 Google Inc. 49 | 50 | * coredumper: version 1.0 release 51 | * made devel RPMs depend on the runtime-only package. 52 | * fixed signal related system calls on x86_64. 53 | * wrote manual pages. 54 | 55 | Tue Feb 20 15:07:03 2007 Google Inc. 56 | 57 | * changed from NT_PRFPXREG to NT_PRXFPREG, as this appears to be 58 | what the kernel and the binary tool chain finally agrees on. 59 | 60 | * dump anonymous executable mappins such as the [vdso] segment. 61 | This helps "gdb" in following call chains past the invocation of 62 | signal handlers. 63 | 64 | Fri Jan 25 18:36:01 2008 Google Inc. 65 | 66 | * Added kernel data structures to linux_syscall_support.h 67 | * Added some more system calls 68 | * General clean ups and minor bug fixes to linux_syscall_support.h 69 | * Updated MIPS support 70 | * Added PPC support to linux_syscall_support.h (based on the patch at 71 | http://google-perftools.googlegroups.com/web/google-perftools-0.94.1.ppc.patch?gda=k9bft1IAAACubrlYz6X6f2r_QSIc5WKIP3FyvVAXIQ9N70rJj7w7MWG1qiJ7UbTIup-M2XPURDR0OdCHCKqS2f7o1Lzcc8Kg4jvJEVA5r4WYNVZfjSxuln7gCK2zepjMSjyreBgvHJk) 72 | This does not mean that the coredumper works on PPC, yet. That still 73 | requires additional work 74 | * Added linux_syscall_support_unittest.cc 75 | * Updated other files as needed so that they would work with the 76 | changes made to linux_syscall_support.h 77 | 78 | Thu Apr 3 14:16:01 2008 Google Inc. 79 | 80 | * coredumper: version 1.2 release 81 | * Added the option to prioritize smaller memory segments when limiting 82 | core dumps. 83 | * Added the option to add user defined notes into the core dump. 84 | * Added a generalized system to be able to combine parameters easily. 85 | * Increased the library version number to 1.0.0 since the interface has 86 | been extended. 87 | * Added vdso segments to the core dump. 88 | * Made the failing thread's registers the first in the core file as 89 | expected by gdb. 90 | 91 | Fri Apr 4 09:38:05 2008 Google Inc. 92 | 93 | * coredumper: version 1.2.1 release 94 | * Fixed a problem which occurs if auxv vectors aren't supported. 95 | 96 | -------------------------------------------------------------------------------- /man/WriteCoreDump.man: -------------------------------------------------------------------------------- 1 | '\" t 2 | .TH WRITECOREDUMP 3 "Feb 15, 2007" 3 | .SH NAME 4 | WriteCoreDump, WriteCoreDumpWith, WriteCoreDumpLimited, 5 | WriteCoreDumpLimitedByPriority, WriteCompressedCoreDump \- writes a snapshot of the 6 | current process 7 | .SH SYNOPSIS 8 | .ad l 9 | .PP 10 | .B "#include \*(lqgoogle/coredumper.h\*(rq" 11 | .PP 12 | .BI int\~WriteCoreDump(const\~char\~* file_name ); 13 | .PP 14 | .BI int\~WriteCoreDumpWith(const\~char\ \:* file_name ,\ \:const\~struct\~Core\%Dump\%Parameters\ \:* params ); 15 | .PP 16 | .BI int\~WriteCoreDumpLimited(const\~char\ \:* file_name ,\ \:size_t\~ \ 17 | \:max_length ); 18 | .PP 19 | .BI int\~WriteCoreDumpLimitedByPriority(const\~char\ \:* file_name ,\ \:size_t\~ \ 20 | \:max_length ); 21 | .HP 28 22 | .BI int\~Write\%Compressed\%Core\%Dump(const\~char\ \:* file_name \ 23 | ,\ \:size_t\ \: max_length ,\ \:const\~struct\~Coredumper\%Compressor\ \ 24 | \:compressors [],\ \:struct\~Coredumper\%Compressor\ \:** \ 25 | selected_compressor ); 26 | .PP 27 | .ad b 28 | .SH DESCRIPTION 29 | The \fBWriteCoreDump\fP() function writes a core file to 30 | .IR file_name . 31 | The calling process continues running after the file has been 32 | written. This is a convenience wrapper for \fBWriteCoreDumpWith\fP() using the 33 | default parameters. 34 | .PP 35 | The \fBWriteCoreDumpWith\fP() function writes a core file to 36 | .IR file_name 37 | using the parameters specified in the 38 | \fBCoreDumpParameters\fP() structure. This allows for various combinations of 39 | configurations. 40 | .PP 41 | The \fBWriteCoreDumpLimited\fP() function restricts the maximum length 42 | of the written file. This is similar to what setting calling 43 | .BR setrlimit (2) 44 | does for system-generated core files. This is a convenience wrapper for 45 | \fBWriteCoreDumpWith\fP(). 46 | .PP 47 | The \fBWriteCoreDumpLimitedByPriority\fP() function restricts the maximum length 48 | of the written file, however it does so by prioritizing smaller memory 49 | segments. This means that the core file is not truncated at the end of the 50 | file, as in 51 | \fBWriteCoreDumpLimited\fP(), but individual memory segments in the core file 52 | are truncated with the largest segments truncated first. This is a convenience 53 | wrapper for \fBWriteCoreDumpWith\fP(). 54 | .PP 55 | The \fBWriteCompressedCoreDump\fP() function attempts to compress the 56 | core file on the fly, if a suitable 57 | .I compressor 58 | could be located. 59 | .PP 60 | If 61 | .IR selected_compressor 62 | is non-NULL, it will be set to the actual 63 | .I CoredumperCompressor 64 | object used. 65 | .PP 66 | The 67 | .I filename 68 | automatically has a suitable suffix appended to it. Normally this 69 | would be \*(lq.bz2\*(rq for 70 | .BR bzip2 (1) 71 | compression, \*(lq.gz\*(rq for 72 | .BR gzip (1) 73 | compression, or \*(lq.Z\*(rq for 74 | .BR compress (1) 75 | compression. This behavior can be changed by defining custom 76 | .I CoredumperCompressor 77 | descriptions. This is a convenience wrapper for \fBWriteCoreDumpWith\fP(). See 78 | the manual page for 79 | .BR GetCoreDump (3) 80 | for more details. 81 | .SH RETURN VALUE 82 | \fBWriteCoreDump\fP(), \fBWriteCoreDumpWith\fP(), \fBWriteCoreDumpLimited\fP(), 83 | \fBWriteCoreDumpLimitedByPriority\fP(), and 84 | \fBWriteCompressedCoreDump\fP() return zero on success and \-1 on 85 | failure. In case of failure, 86 | .I errno 87 | will be set appropriately. 88 | .SH ERRORS 89 | The most common reason for failure is for another process to already 90 | use the debugging API that is needed to generate the core 91 | files. This could, for instance, be 92 | .BR gdb (1), 93 | or 94 | .BR strace(1). 95 | .SH NOTES 96 | The coredumper functions momentarily suspend all threads, while 97 | creating a COW (copy-on-write) copy of the process's address space. 98 | .PP 99 | The functions are neither reentrant nor async signal safe. Callers 100 | should wrap a mutex around their invocation, if necessary. 101 | .PP 102 | The current implementation tries very hard to behave reasonably when 103 | called from a signal handler, but no guarantees are made that this 104 | will always work. Most importantly, it is the caller's responsibility 105 | to make sure that there are never more than one instance of functions 106 | from the \fBGetCoreDump\fP() or \fBWriteCoreDump\fP() family executing 107 | concurrently. 108 | .SH "SEE ALSO" 109 | .BR GetCoreDump (3), 110 | .BR GetCoreDumpWith (3), 111 | .BR GetCompressedCoreDump(3), 112 | and 113 | .BR CoreDumpParameters (3). 114 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to produce Makefile.in 2 | 3 | # This is so we can #include 4 | AM_CPPFLAGS = -I$(top_srcdir)/src 5 | 6 | googleincludedir = $(includedir)/google 7 | ## The .h files you want to install (that is, .h files that people 8 | ## who install this package can include in their own applications.) 9 | googleinclude_HEADERS = 10 | 11 | docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION) 12 | ## This is for HTML and other documentation you want to install. 13 | ## Add your documentation files (in doc/) in addition to these 14 | ## top-level boilerplate files. Also add a TODO file if you have one. 15 | dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README TODO 16 | 17 | ## The libraries (.so's) you want to install 18 | lib_LTLIBRARIES = 19 | 20 | ## unittests you want to run when people type 'make check'. 21 | ## TESTS is for binary unittests, check_SCRIPTS for script-based unittests. 22 | ## TESTS_ENVIRONMENT sets environment variables for when you run unittest, 23 | ## but it only seems to take effect for *binary* unittests (argh!) 24 | TESTS = 25 | check_SCRIPTS = 26 | TESTS_ENVIRONMENT = 27 | # Every time you add a unittest to check_SCRIPTS, add it here too 28 | noinst_SCRIPTS = 29 | 30 | # The manual pages that should be installed 31 | man3_MANS = man/GetCoreDump.man man/WriteCoreDump.man \ 32 | man/CoreDumpParameters.man 33 | 34 | install-data-hook: 35 | ln -sf GetCoreDump.3 $(DESTDIR)$(man3dir)/GetCompressedCoreDump.3 36 | ln -sf GetCoreDump.3 $(DESTDIR)$(man3dir)/GetCoreDumpWith.3 37 | ln -sf WriteCoreDump.3 $(DESTDIR)$(man3dir)/WriteCompressedCoreDump.3 38 | ln -sf WriteCoreDump.3 $(DESTDIR)$(man3dir)/WriteCoreDumpWith.3 39 | ln -sf WriteCoreDump.3 $(DESTDIR)$(man3dir)/WriteCoreDumpLimited.3 40 | ln -sf WriteCoreDump.3 $(DESTDIR)$(man3dir)/WriteCoreDumpLimitedByPriority.3 41 | ln -sf CoreDumpParameters.3 $(DESTDIR)$(man3dir)/ClearCoreDumpParameters.3 42 | ln -sf CoreDumpParameters.3 $(DESTDIR)$(man3dir)/SetCoreDumpLimited.3 43 | ln -sf CoreDumpParameters.3 $(DESTDIR)$(man3dir)/SetCoreDumpCompressed.3 44 | ln -sf CoreDumpParameters.3 $(DESTDIR)$(man3dir)/SetCoreDumpLimitedByPriority.3 45 | ln -sf CoreDumpParameters.3 $(DESTDIR)$(man3dir)/SetCoreDumpNotes.3 46 | 47 | 48 | uninstall-hook: 49 | rm -f $(DESTDIR)$(man3dir)/GetCompressedCoreDump.3 50 | rm -f $(DESTDIR)$(man3dir)/GetCoreDumpWith.3 51 | rm -f $(DESTDIR)$(man3dir)/WriteCoreDumpWith.3 52 | rm -f $(DESTDIR)$(man3dir)/WriteCompressedCoreDump.3 53 | rm -f $(DESTDIR)$(man3dir)/WriteCoreDumpLimited.3 54 | rm -f $(DESTDIR)$(man3dir)/WriteCoreDumpLimitedByPriority.3 55 | rm -f $(DESTDIR)$(man3dir)/ClearCoreDumpParameters.3 56 | rm -f $(DESTDIR)$(man3dir)/SetCoreDumpLimited.3 57 | rm -f $(DESTDIR)$(man3dir)/SetCoreDumpCompressed.3 58 | rm -f $(DESTDIR)$(man3dir)/SetCoreDumpLimitedByPriority.3 59 | rm -f $(DESTDIR)$(man3dir)/SetCoreDumpNotes.3 60 | 61 | ## vvvv RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS 62 | 63 | lib_LTLIBRARIES += libcoredumper.la 64 | LIBCOREDUMPER_INCLUDES = src/google/coredumper.h src/elfcore.h \ 65 | src/linux_syscall_support.h src/linuxthreads.h \ 66 | src/thread_lister.h 67 | googleinclude_HEADERS += src/google/coredumper.h 68 | libcoredumper_la_SOURCES = src/coredumper.c \ 69 | src/thread_lister.c \ 70 | src/elfcore.c \ 71 | src/linuxthreads.c \ 72 | $(LIBCOREDUMPER_INCLUDES) 73 | libcoredumper_la_LDFLAGS = -export-symbols $(top_srcdir)/src/libcoredumper.sym \ 74 | -version-info 1:0:0 75 | 76 | TESTS += coredumper_unittest linux_syscall_support_unittest 77 | COREDUMP_UNITTEST_INCLUDES = src/google/coredumper.h 78 | coredumper_unittest_SOURCES = src/coredumper_unittest.c 79 | coredumper_unittest_LDADD = libcoredumper.la -lpthread 80 | LINUX_SYSCALL_SUPPORT_INCLUDES = src/linux_syscall_support.h 81 | linux_syscall_support_unittest_SOURCES = src/linux_syscall_support_unittest.cc 82 | 83 | ## ^^^^ END OF RULES TO MAKE THE LIBRARIES, BINARIES, AND UNITTESTS 84 | 85 | 86 | ## This should always include $(TESTS), but may also include other 87 | ## binaries that you compile but don't want automatically installed. 88 | noinst_PROGRAMS = $(TESTS) 89 | 90 | rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec 91 | @cd packages && ./rpm.sh ${PACKAGE} ${VERSION} 92 | 93 | deb: dist-gzip packages/deb.sh packages/deb/* 94 | @cd packages && ./deb.sh ${PACKAGE} ${VERSION} 95 | 96 | libtool: $(LIBTOOL_DEPS) 97 | $(SHELL) ./config.status --recheck 98 | 99 | EXTRA_DIST = ${man3_MANS} man/GetCoreDump.man man/WriteCoreDump.man \ 100 | packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh \ 101 | packages/deb libtool src/libcoredumper.sym examples/Makefile \ 102 | examples/tftpd.c 103 | 104 | DISTCLEANFILES = core-test 105 | -------------------------------------------------------------------------------- /man/GetCoreDump.man: -------------------------------------------------------------------------------- 1 | '\" t 2 | .TH GETCOREDUMP 3 "Feb 15, 2007" 3 | .SH NAME 4 | GetCoreDump, GetCompressedCoreDump, GetCoreDumpWith \- creates a copy-on-write snapshot 5 | of the current process 6 | .SH SYNOPSIS 7 | .ad l 8 | .PP 9 | .B "#include \*(lqgoogle/coredumper.h\*(rq" 10 | .PP 11 | .B int GetCoreDump(void); 12 | .PP 13 | .BI int\~Get\%Core\%Dump\%With(const\~struct\~Core\%Dump\%Parameters\~* params ); 14 | .HP 26 15 | .BI int\~Get\%Compressed\%Core\%Dump(const\~struct\~Coredumper\%Compressor\ \:\ 16 | compressors[] ,\ \:struct\~Coredumper\%Compressor\ \:** selected_compressor ); 17 | .ad b 18 | .SH DESCRIPTION 19 | The \fBGetCoreDump\fP() function returns a file handle that can be 20 | read to obtain a snapshot of the current state of the calling process. This 21 | function is a convenience wrapper for \fBGetCoreDumpWith\fP() using the default 22 | parameters. 23 | .PP 24 | The \fBGetCoreDumpWith\fP() function returns a file handle that can be read 25 | to obtain a snapshot of the current state of the calling process using the 26 | parameters specified in the \fBCoreDumpParameters\fP structure. The 27 | parameters can specify any behaviour of the core dumper however the limiting 28 | values in the parameter will be ignored in this type of core dump. 29 | .PP 30 | The \fBGetCompressedCoreDump\fP() function returns a file handle to a 31 | core file that has been compressed on the fly. This function is a convenience 32 | wrapper for \fBGetCoreDumpWith\fP(). In 33 | .IR compressor , 34 | the caller passes a pointer to an array of possible compressors: 35 | .sp 36 | .RS 37 | .nf 38 | struct CoredumperCompressor { 39 | const char *compressor; // File name of compressor; e.g. \*(lqgzip\*(rq 40 | const char *const *args; // execv()-style command line arguments 41 | const char *suffix; // File name suffix; e.g. \*(lq.gz\*(rq 42 | }; 43 | .fi 44 | .RE 45 | .PP 46 | The 47 | .I suffix 48 | will be ignored by the \fBGetCoreDump\fP() and 49 | \fBGetCompressedCoreDump\fP() functions, and is only needed for the 50 | \fBWriteCoreDump\fP() family of functions. 51 | .PP 52 | Array entries will be tried in sequence until an executable compressor 53 | has been found or the end of the array has been reached. The end is 54 | signalled by an entry that has been zero'd out completely. An empty 55 | string in place of the 56 | .I compressor 57 | name signals that no compression should be performed. 58 | .PP 59 | There are several pre-defined compressor descriptions available: 60 | .TP \w'COREDUMPER_'u 61 | .B COREDUMPER_COMPRESSED 62 | Try compressing with either 63 | .BR bzip2 (1), 64 | .BR gzip (1), 65 | or 66 | .BR compress (1). 67 | If all of those fail, fall back on generating an uncompressed image. 68 | .TP 69 | .B COREDUMPER_BZIP2_COMPRESSED 70 | .TP 71 | .B COREDUMPER_GZIP_COMPRESSED 72 | .TP 73 | .B COREDUMPER_COMPRESS_COMPRESSED 74 | Try compressing with a specific compressor. Fail if no compressor could 75 | be found. 76 | .TP 77 | .B COREDUMPER_TRY_BZIP2_COMPRESSED 78 | .TP 79 | .B COREDUMPER_TRY_GZIP_COMPRESSED 80 | .TP 81 | .B COREDUMPER_TRY_COMPRESS_COMPRESSED 82 | Try compressing with a specific compressor. Fall back on generating an 83 | uncompressed image, if the specified compressor is unavailable. 84 | .TP 85 | .B COREDUMPER_UNCOMPRESSED 86 | Always create an uncompressed core file. 87 | .PP 88 | If 89 | .I selected_compressor 90 | is non-NULL, it will be set to the actual 91 | .I CoredumperCompressor 92 | object used. 93 | .SH RETURN VALUE 94 | \fBGetCoreDump\fP(), \fBGetCoreDumpWith\fP(), and \fBGetCompressedCoreDump\fP() 95 | all return a non-seekable file handle on success. The copy-on-write snapshot 96 | will automatically be released, when the caller \fBclose\fP()s this file 97 | handle. 98 | .PP 99 | On error \-1 will be returned and 100 | .I errno 101 | will be set appropriately. 102 | .SH ERRORS 103 | The most common reason for failure is for another process to already 104 | use the debugging API that is needed to generate the core 105 | files. This could, for instance, be 106 | .BR gdb (1), 107 | or 108 | .BR strace(1). 109 | .SH NOTES 110 | The coredumper functions momentarily suspend all threads, while 111 | creating a COW (copy-on-write) copy of the process's address 112 | space. The snapshot shows up as a new child process of the current 113 | process, but memory requirements are relatively small, as most pages 114 | are shared between parent and child. 115 | .PP 116 | The functions are neither reentrant nor async signal safe. Callers 117 | should wrap a mutex around their invocation, if necessary. 118 | .PP 119 | The current implementation tries very hard to behave reasonably when 120 | called from a signal handler, but no guarantees are made that this 121 | will always work. Most importantly, it is the caller's responsibility 122 | to make sure that there are never more than one instance of functions 123 | from the \fBGetCoreDump\fP() or \fBWriteCoreDump\fP() family executing 124 | concurrently. 125 | .SH "SEE ALSO" 126 | .BR WriteCoreDump (3), 127 | .BR WriteCoreDumpWith (3), 128 | .BR WriteCoreDumpLimited (3), 129 | .BR WriteCoreDumpLimitedByPriority (3), 130 | .BR WriteCompressedCoreDump(3), 131 | and 132 | .BR CoreDumpParameters (3). 133 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software 2 | Foundation, Inc. 3 | 4 | This file is free documentation; the Free Software Foundation gives 5 | unlimited permission to copy, distribute and modify it. 6 | 7 | Basic Installation 8 | ================== 9 | 10 | These are generic installation instructions. 11 | 12 | The `configure' shell script attempts to guess correct values for 13 | various system-dependent variables used during compilation. It uses 14 | those values to create a `Makefile' in each directory of the package. 15 | It may also create one or more `.h' files containing system-dependent 16 | definitions. Finally, it creates a shell script `config.status' that 17 | you can run in the future to recreate the current configuration, and a 18 | file `config.log' containing compiler output (useful mainly for 19 | debugging `configure'). 20 | 21 | It can also use an optional file (typically called `config.cache' 22 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 23 | the results of its tests to speed up reconfiguring. (Caching is 24 | disabled by default to prevent problems with accidental use of stale 25 | cache files.) 26 | 27 | If you need to do unusual things to compile the package, please try 28 | to figure out how `configure' could check whether to do them, and mail 29 | diffs or instructions to the address given in the `README' so they can 30 | be considered for the next release. If you are using the cache, and at 31 | some point `config.cache' contains results you don't want to keep, you 32 | may remove or edit it. 33 | 34 | The file `configure.ac' (or `configure.in') is used to create 35 | `configure' by a program called `autoconf'. You only need 36 | `configure.ac' if you want to change it or regenerate `configure' using 37 | a newer version of `autoconf'. 38 | 39 | The simplest way to compile this package is: 40 | 41 | 1. `cd' to the directory containing the package's source code and type 42 | `./configure' to configure the package for your system. If you're 43 | using `csh' on an old version of System V, you might need to type 44 | `sh ./configure' instead to prevent `csh' from trying to execute 45 | `configure' itself. 46 | 47 | Running `configure' takes awhile. While running, it prints some 48 | messages telling which features it is checking for. 49 | 50 | 2. Type `make' to compile the package. 51 | 52 | 3. Optionally, type `make check' to run any self-tests that come with 53 | the package. 54 | 55 | 4. Type `make install' to install the programs and any data files and 56 | documentation. 57 | 58 | Alternatively, you can build package files for various target 59 | distributions: 60 | 61 | `make dist` - builds a source .tar.gz file 62 | `make deb` - builds Debian packages 63 | `make rpm` - build RedHat RPM packages 64 | 65 | The source .tar.gz file will be created in the package's top level 66 | directory. All other distribution-specific packages will be created 67 | in the `package' directory. The make targets print out the exact 68 | location of these files. 69 | 70 | 5. You can remove the program binaries and object files from the 71 | source code directory by typing `make clean'. To also remove the 72 | files that `configure' created (so you can compile the package for 73 | a different kind of computer), type `make distclean'. There is 74 | also a `make maintainer-clean' target, but that is intended mainly 75 | for the package's developers. If you use it, you may have to get 76 | all sorts of other programs in order to regenerate files that came 77 | with the distribution. 78 | 79 | Compilers and Options 80 | ===================== 81 | 82 | Some systems require unusual options for compilation or linking that 83 | the `configure' script does not know about. Run `./configure --help' 84 | for details on some of the pertinent environment variables. 85 | 86 | You can give `configure' initial values for configuration parameters 87 | by setting variables in the command line or in the environment. Here 88 | is an example: 89 | 90 | ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix 91 | 92 | *Note Defining Variables::, for more details. 93 | 94 | Compiling For Multiple Architectures 95 | ==================================== 96 | 97 | You can compile the package for more than one kind of computer at the 98 | same time, by placing the object files for each architecture in their 99 | own directory. To do this, you must use a version of `make' that 100 | supports the `VPATH' variable, such as GNU `make'. `cd' to the 101 | directory where you want the object files and executables to go and run 102 | the `configure' script. `configure' automatically checks for the 103 | source code in the directory that `configure' is in and in `..'. 104 | 105 | If you have to use a `make' that does not support the `VPATH' 106 | variable, you have to compile the package for one architecture at a 107 | time in the source code directory. After you have installed the 108 | package for one architecture, use `make distclean' before reconfiguring 109 | for another architecture. 110 | 111 | Installation Names 112 | ================== 113 | 114 | By default, `make install' will install the package's files in 115 | `/usr/local/bin', `/usr/local/man', etc. You can specify an 116 | installation prefix other than `/usr/local' by giving `configure' the 117 | option `--prefix=PATH'. 118 | 119 | You can specify separate installation prefixes for 120 | architecture-specific files and architecture-independent files. If you 121 | give `configure' the option `--exec-prefix=PATH', the package will use 122 | PATH as the prefix for installing programs and libraries. 123 | Documentation and other data files will still use the regular prefix. 124 | 125 | In addition, if you use an unusual directory layout you can give 126 | options like `--bindir=PATH' to specify different values for particular 127 | kinds of files. Run `configure --help' for a list of the directories 128 | you can set and what kinds of files go in them. 129 | 130 | If the package supports it, you can cause programs to be installed 131 | with an extra prefix or suffix on their names by giving `configure' the 132 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 133 | 134 | Optional Features 135 | ================= 136 | 137 | Some packages pay attention to `--enable-FEATURE' options to 138 | `configure', where FEATURE indicates an optional part of the package. 139 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 140 | is something like `gnu-as' or `x' (for the X Window System). The 141 | `README' should mention any `--enable-' and `--with-' options that the 142 | package recognizes. 143 | 144 | For packages that use the X Window System, `configure' can usually 145 | find the X include and library files automatically, but if it doesn't, 146 | you can use the `configure' options `--x-includes=DIR' and 147 | `--x-libraries=DIR' to specify their locations. 148 | 149 | Specifying the System Type 150 | ========================== 151 | 152 | There may be some features `configure' cannot figure out 153 | automatically, but needs to determine by the type of machine the package 154 | will run on. Usually, assuming the package is built to be run on the 155 | _same_ architectures, `configure' can figure that out, but if it prints 156 | a message saying it cannot guess the machine type, give it the 157 | `--build=TYPE' option. TYPE can either be a short name for the system 158 | type, such as `sun4', or a canonical name which has the form: 159 | 160 | CPU-COMPANY-SYSTEM 161 | 162 | where SYSTEM can have one of these forms: 163 | 164 | OS KERNEL-OS 165 | 166 | See the file `config.sub' for the possible values of each field. If 167 | `config.sub' isn't included in this package, then this package doesn't 168 | need to know the machine type. 169 | 170 | If you are _building_ compiler tools for cross-compiling, you should 171 | use the `--target=TYPE' option to select the type of system they will 172 | produce code for. 173 | 174 | If you want to _use_ a cross compiler, that generates code for a 175 | platform different from the build platform, you should specify the 176 | "host" platform (i.e., that on which the generated programs will 177 | eventually be run) with `--host=TYPE'. 178 | 179 | Sharing Defaults 180 | ================ 181 | 182 | If you want to set default values for `configure' scripts to share, 183 | you can create a site shell script called `config.site' that gives 184 | default values for variables like `CC', `cache_file', and `prefix'. 185 | `configure' looks for `PREFIX/share/config.site' if it exists, then 186 | `PREFIX/etc/config.site' if it exists. Or, you can set the 187 | `CONFIG_SITE' environment variable to the location of the site script. 188 | A warning: not all `configure' scripts look for a site script. 189 | 190 | Defining Variables 191 | ================== 192 | 193 | Variables not defined in a site shell script can be set in the 194 | environment passed to `configure'. However, some packages may run 195 | configure again during the build, and the customized values of these 196 | variables may be lost. In order to avoid this problem, you should set 197 | them in the `configure' command line, using `VAR=value'. For example: 198 | 199 | ./configure CC=/usr/local2/bin/gcc 200 | 201 | will cause the specified gcc to be used as the C compiler (unless it is 202 | overridden in the site shell script). 203 | 204 | `configure' Invocation 205 | ====================== 206 | 207 | `configure' recognizes the following options to control how it 208 | operates. 209 | 210 | `--help' 211 | `-h' 212 | Print a summary of the options to `configure', and exit. 213 | 214 | `--version' 215 | `-V' 216 | Print the version of Autoconf used to generate the `configure' 217 | script, and exit. 218 | 219 | `--cache-file=FILE' 220 | Enable the cache: use and save the results of the tests in FILE, 221 | traditionally `config.cache'. FILE defaults to `/dev/null' to 222 | disable caching. 223 | 224 | `--config-cache' 225 | `-C' 226 | Alias for `--cache-file=config.cache'. 227 | 228 | `--quiet' 229 | `--silent' 230 | `-q' 231 | Do not print messages saying which checks are being made. To 232 | suppress all normal output, redirect it to `/dev/null' (any error 233 | messages will still be shown). 234 | 235 | `--srcdir=DIR' 236 | Look for the package's source code in directory DIR. Usually 237 | `configure' can determine that directory automatically. 238 | 239 | `configure' also accepts some other, not widely useful, options. Run 240 | `configure --help' for more details. 241 | 242 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install - install a program, script, or datafile 3 | 4 | scriptversion=2005-05-14.22 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. It can only install one file at a time, a restriction 43 | # shared with many OS's install programs. 44 | 45 | # set DOITPROG to echo to test this script 46 | 47 | # Don't use :- since 4.3BSD and earlier shells don't like it. 48 | doit="${DOITPROG-}" 49 | 50 | # put in absolute paths if you don't have them in your path; or use env. vars. 51 | 52 | mvprog="${MVPROG-mv}" 53 | cpprog="${CPPROG-cp}" 54 | chmodprog="${CHMODPROG-chmod}" 55 | chownprog="${CHOWNPROG-chown}" 56 | chgrpprog="${CHGRPPROG-chgrp}" 57 | stripprog="${STRIPPROG-strip}" 58 | rmprog="${RMPROG-rm}" 59 | mkdirprog="${MKDIRPROG-mkdir}" 60 | 61 | chmodcmd="$chmodprog 0755" 62 | chowncmd= 63 | chgrpcmd= 64 | stripcmd= 65 | rmcmd="$rmprog -f" 66 | mvcmd="$mvprog" 67 | src= 68 | dst= 69 | dir_arg= 70 | dstarg= 71 | no_target_directory= 72 | 73 | usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 74 | or: $0 [OPTION]... SRCFILES... DIRECTORY 75 | or: $0 [OPTION]... -t DIRECTORY SRCFILES... 76 | or: $0 [OPTION]... -d DIRECTORIES... 77 | 78 | In the 1st form, copy SRCFILE to DSTFILE. 79 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 80 | In the 4th, create DIRECTORIES. 81 | 82 | Options: 83 | -c (ignored) 84 | -d create directories instead of installing files. 85 | -g GROUP $chgrpprog installed files to GROUP. 86 | -m MODE $chmodprog installed files to MODE. 87 | -o USER $chownprog installed files to USER. 88 | -s $stripprog installed files. 89 | -t DIRECTORY install into DIRECTORY. 90 | -T report an error if DSTFILE is a directory. 91 | --help display this help and exit. 92 | --version display version info and exit. 93 | 94 | Environment variables override the default commands: 95 | CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 96 | " 97 | 98 | while test -n "$1"; do 99 | case $1 in 100 | -c) shift 101 | continue;; 102 | 103 | -d) dir_arg=true 104 | shift 105 | continue;; 106 | 107 | -g) chgrpcmd="$chgrpprog $2" 108 | shift 109 | shift 110 | continue;; 111 | 112 | --help) echo "$usage"; exit $?;; 113 | 114 | -m) chmodcmd="$chmodprog $2" 115 | shift 116 | shift 117 | continue;; 118 | 119 | -o) chowncmd="$chownprog $2" 120 | shift 121 | shift 122 | continue;; 123 | 124 | -s) stripcmd=$stripprog 125 | shift 126 | continue;; 127 | 128 | -t) dstarg=$2 129 | shift 130 | shift 131 | continue;; 132 | 133 | -T) no_target_directory=true 134 | shift 135 | continue;; 136 | 137 | --version) echo "$0 $scriptversion"; exit $?;; 138 | 139 | *) # When -d is used, all remaining arguments are directories to create. 140 | # When -t is used, the destination is already specified. 141 | test -n "$dir_arg$dstarg" && break 142 | # Otherwise, the last argument is the destination. Remove it from $@. 143 | for arg 144 | do 145 | if test -n "$dstarg"; then 146 | # $@ is not empty: it contains at least $arg. 147 | set fnord "$@" "$dstarg" 148 | shift # fnord 149 | fi 150 | shift # arg 151 | dstarg=$arg 152 | done 153 | break;; 154 | esac 155 | done 156 | 157 | if test -z "$1"; then 158 | if test -z "$dir_arg"; then 159 | echo "$0: no input file specified." >&2 160 | exit 1 161 | fi 162 | # It's OK to call `install-sh -d' without argument. 163 | # This can happen when creating conditional directories. 164 | exit 0 165 | fi 166 | 167 | for src 168 | do 169 | # Protect names starting with `-'. 170 | case $src in 171 | -*) src=./$src ;; 172 | esac 173 | 174 | if test -n "$dir_arg"; then 175 | dst=$src 176 | src= 177 | 178 | if test -d "$dst"; then 179 | mkdircmd=: 180 | chmodcmd= 181 | else 182 | mkdircmd=$mkdirprog 183 | fi 184 | else 185 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 186 | # might cause directories to be created, which would be especially bad 187 | # if $src (and thus $dsttmp) contains '*'. 188 | if test ! -f "$src" && test ! -d "$src"; then 189 | echo "$0: $src does not exist." >&2 190 | exit 1 191 | fi 192 | 193 | if test -z "$dstarg"; then 194 | echo "$0: no destination specified." >&2 195 | exit 1 196 | fi 197 | 198 | dst=$dstarg 199 | # Protect names starting with `-'. 200 | case $dst in 201 | -*) dst=./$dst ;; 202 | esac 203 | 204 | # If destination is a directory, append the input filename; won't work 205 | # if double slashes aren't ignored. 206 | if test -d "$dst"; then 207 | if test -n "$no_target_directory"; then 208 | echo "$0: $dstarg: Is a directory" >&2 209 | exit 1 210 | fi 211 | dst=$dst/`basename "$src"` 212 | fi 213 | fi 214 | 215 | # This sed command emulates the dirname command. 216 | dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 217 | 218 | # Make sure that the destination directory exists. 219 | 220 | # Skip lots of stat calls in the usual case. 221 | if test ! -d "$dstdir"; then 222 | defaultIFS=' 223 | ' 224 | IFS="${IFS-$defaultIFS}" 225 | 226 | oIFS=$IFS 227 | # Some sh's can't handle IFS=/ for some reason. 228 | IFS='%' 229 | set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230 | shift 231 | IFS=$oIFS 232 | 233 | pathcomp= 234 | 235 | while test $# -ne 0 ; do 236 | pathcomp=$pathcomp$1 237 | shift 238 | if test ! -d "$pathcomp"; then 239 | $mkdirprog "$pathcomp" 240 | # mkdir can fail with a `File exist' error in case several 241 | # install-sh are creating the directory concurrently. This 242 | # is OK. 243 | test -d "$pathcomp" || exit 244 | fi 245 | pathcomp=$pathcomp/ 246 | done 247 | fi 248 | 249 | if test -n "$dir_arg"; then 250 | $doit $mkdircmd "$dst" \ 251 | && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252 | && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253 | && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254 | && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 255 | 256 | else 257 | dstfile=`basename "$dst"` 258 | 259 | # Make a couple of temp file names in the proper directory. 260 | dsttmp=$dstdir/_inst.$$_ 261 | rmtmp=$dstdir/_rm.$$_ 262 | 263 | # Trap to clean up those temp files at exit. 264 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265 | trap '(exit $?); exit' 1 2 13 15 266 | 267 | # Copy the file name to the temp name. 268 | $doit $cpprog "$src" "$dsttmp" && 269 | 270 | # and set any options; do chmod last to preserve setuid bits. 271 | # 272 | # If any of these fail, we abort the whole thing. If we want to 273 | # ignore errors from any of these, just make sure not to ignore 274 | # errors from the above "$doit $cpprog $src $dsttmp" command. 275 | # 276 | { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277 | && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278 | && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279 | && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 280 | 281 | # Now rename the file to the real destination. 282 | { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283 | || { 284 | # The rename failed, perhaps because mv can't rename something else 285 | # to itself, or perhaps because mv is so ancient that it does not 286 | # support -f. 287 | 288 | # Now remove or move aside any old file at destination location. 289 | # We try this two ways since rm can't unlink itself on some 290 | # systems and the destination file might be busy for other 291 | # reasons. In this case, the final cleanup might fail but the new 292 | # file should still install successfully. 293 | { 294 | if test -f "$dstdir/$dstfile"; then 295 | $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296 | || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297 | || { 298 | echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299 | (exit 1); exit 1 300 | } 301 | else 302 | : 303 | fi 304 | } && 305 | 306 | # Now rename the file to the real destination. 307 | $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308 | } 309 | } 310 | fi || { (exit 1); exit 1; } 311 | done 312 | 313 | # The final little trick to "correctly" pass the exit status to the exit trap. 314 | { 315 | (exit 0); exit 0 316 | } 317 | 318 | # Local variables: 319 | # eval: (add-hook 'write-file-hooks 'time-stamp) 320 | # time-stamp-start: "scriptversion=" 321 | # time-stamp-format: "%:y-%02m-%02d.%02H" 322 | # time-stamp-end: "$" 323 | # End: 324 | -------------------------------------------------------------------------------- /src/google/coredumper.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2008, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Markus Gutschke, Carl Crous 32 | * 33 | * Code to extract a core dump snapshot of the current process. 34 | */ 35 | #ifndef _COREDUMP_H 36 | #define _COREDUMP_H 37 | 38 | #include 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | /* Description of external compressor programs to use for creating compressed 45 | * coredumps. There are a few predefined compressor descriptions; callers 46 | * can also define their own compressors. 47 | * All functions expect an array of compressors. Array entries will be tried 48 | * in sequence until an executable compressor has been found. An empty 49 | * c-string in place of the compressor name signals that no compression should 50 | * be performed. 51 | * The end of the array is signalled by an entry that is completely zero'd out. 52 | */ 53 | struct CoredumperCompressor { 54 | const char *compressor; /* File name of compressor; e.g. gzip */ 55 | const char *const *args;/* execv()-style command line arguments */ 56 | const char *suffix; /* Suffix that should be appended; e.g. .gz */ 57 | }; 58 | 59 | /* Description of a elf note for use in the PT_NOTES section of the core file. 60 | */ 61 | struct CoredumperNote { 62 | const char *name; /* The vendor name */ 63 | unsigned int type; /* A vendor specific type */ 64 | unsigned int description_size; /* The size of the description field */ 65 | const void *description; /* The note data */ 66 | }; 67 | 68 | /* Parameters used to control the core dumper. Future versions of this 69 | * structure must be backwards compatible so any new fields must be appended to 70 | * the end. 71 | */ 72 | struct CoreDumpParameters { 73 | /* The size of this structure. This is used to make sure future versions are 74 | * backwards compatible. 75 | */ 76 | size_t size; 77 | /* Specific settings for the core dumper. See COREDUMPER_FLAG_* */ 78 | int flags; 79 | /* The maximum file size for the core dump. */ 80 | size_t max_length; 81 | /* The set of compressors to choose from. */ 82 | const struct CoredumperCompressor *compressors; 83 | /* After dumping a compressed core, this will be set to the compressor which 84 | * was used to compress the core file. 85 | */ 86 | struct CoredumperCompressor **selected_compressor; 87 | /* Extra notes to write to the core file notes section. */ 88 | const struct CoredumperNote *notes; 89 | /* The amount of notes in the notes array. */ 90 | int note_count; 91 | }; 92 | 93 | /* The core file is limited in size and max_length denotes the maximum size. If 94 | * the core file exceeds this maximum, the file will be truncated. 95 | */ 96 | #define COREDUMPER_FLAG_LIMITED 1 97 | 98 | /* The core file is limited in size and max_length denotes the maximum size. If 99 | * the core file exceeds this maximum, the largest memory segments will be 100 | * reduced or removed first in order to preserve the smaller ones. 101 | */ 102 | #define COREDUMPER_FLAG_LIMITED_BY_PRIORITY 2 103 | 104 | /* Try compressing with either bzip2, gzip, or compress. If all of those fail, 105 | * fall back on generating an uncompressed file. 106 | */ 107 | extern const struct CoredumperCompressor COREDUMPER_COMPRESSED[]; 108 | 109 | /* Try compressing with a specific compressor. Fail if no compressor could 110 | * be found. 111 | */ 112 | extern const struct CoredumperCompressor COREDUMPER_BZIP2_COMPRESSED[]; 113 | extern const struct CoredumperCompressor COREDUMPER_GZIP_COMPRESSED[]; 114 | extern const struct CoredumperCompressor COREDUMPER_COMPRESS_COMPRESSED[]; 115 | 116 | /* Try compressing with a specific compressor. Fall back on generating an 117 | * uncompressed file, if the specified compressor is unavailable. 118 | */ 119 | extern const struct CoredumperCompressor COREDUMPER_TRY_BZIP2_COMPRESSED[]; 120 | extern const struct CoredumperCompressor COREDUMPER_TRY_GZIP_COMPRESSED[]; 121 | extern const struct CoredumperCompressor COREDUMPER_TRY_COMPRESS_COMPRESSED[]; 122 | 123 | /* Always create an uncompressed core file. 124 | */ 125 | extern const struct CoredumperCompressor COREDUMPER_UNCOMPRESSED[]; 126 | 127 | /* Returns a file handle that can be read to obtain a snapshot of the 128 | * current state of this process. If a core file could not be 129 | * generated for any reason, -1 is returned and "errno" will be set 130 | * appropriately. 131 | * 132 | * This function momentarily suspends all threads, while creating a 133 | * COW (copy-on-write) copy of the process's address space. 134 | * 135 | * This function is neither reentrant nor async signal safe. Callers 136 | * should wrap a mutex around the invocation of this function, if necessary. 137 | * 138 | * The current implementation tries very hard to behave reasonably when 139 | * called from a signal handler, but no guarantees are made that this will 140 | * always work. Most importantly, it is the caller's responsibility to 141 | * make sure that there are never more than one instance of GetCoreDump() 142 | * or WriteCoreDump() executing concurrently. 143 | */ 144 | int GetCoreDump(void); 145 | 146 | /* Gets a core dump with the given parameters. This is not compatible with any 147 | * core size limiting parameters. 148 | */ 149 | int GetCoreDumpWith(const struct CoreDumpParameters *params); 150 | 151 | /* Attempts to compress the core file on the fly, if a suitable compressor 152 | * could be located. Sets "selected_compressor" to the compressor that 153 | * was picked. 154 | */ 155 | int GetCompressedCoreDump(const struct CoredumperCompressor compressors[], 156 | struct CoredumperCompressor **selected_compressor); 157 | 158 | /* Writes the core file to disk. This is a convenience method wrapping 159 | * GetCoreDump(). If a core file could not be generated for any reason, 160 | * -1 is returned and errno is set appropriately. On success, zero is 161 | * returned. 162 | */ 163 | int WriteCoreDump(const char *file_name); 164 | 165 | /* Writes a core dump to the given file with the given parameters. */ 166 | int WriteCoreDumpWith(const struct CoreDumpParameters *params, 167 | const char *file_name); 168 | 169 | /* Callers might need to restrict the maximum size of the core file. This 170 | * convenience method provides the necessary support to emulate "ulimit -c". 171 | */ 172 | int WriteCoreDumpLimited(const char *file_name, size_t max_length); 173 | 174 | /* Writes a limited size core file, however instead of truncating the file at 175 | * the limit, the core dumper will prioritize smaller memory segments. This 176 | * means that a large heap will most likely either be only partially included 177 | * or not included at all. If the max_length is set too small, this could cause 178 | * performance issues. 179 | */ 180 | int WriteCoreDumpLimitedByPriority(const char *file_name, size_t max_length); 181 | 182 | /* Attempts to compress the core file on the fly, if a suitable compressor 183 | * could be located. Sets "selected_compressor" to the compressor that 184 | * was picked. The filename automatically has a suitable suffix appended 185 | * to it. Normally this would be ".bz2" for bzip2 compression ".gz" for 186 | * gzip compression, or ".Z" for compress compression. This behavior can 187 | * be changed by defining custom CoredumperCompressor descriptions. 188 | */ 189 | int WriteCompressedCoreDump(const char *file_name, size_t max_length, 190 | const struct CoredumperCompressor compressors[], 191 | struct CoredumperCompressor **selected_compressor); 192 | 193 | 194 | /* A convenience definition to clear core dump parameters. 195 | */ 196 | #define ClearCoreDumpParameters(p) \ 197 | ClearCoreDumpParametersInternal((p), sizeof(struct CoreDumpParameters)) 198 | 199 | /* Checks if the current version of the coredumper has a specific parameter. 200 | */ 201 | #define CoreDumpParametersHas(p, f) \ 202 | ((p)->size >= offsetof(struct CoreDumpParameters, f) + sizeof((p)->f)) 203 | 204 | /* Sets a coredumper parameter to a given value. This will abort the program if 205 | * the given parameter doesn't exist in the parameters. 206 | */ 207 | #define SetCoreDumpParameter(p, f, v) \ 208 | do { \ 209 | if (!CoreDumpParametersHas(p, f)) { \ 210 | abort(); \ 211 | } \ 212 | (p)->f = (v); \ 213 | } while(0) 214 | 215 | /* Gets a coredumper parameter. If the parameter doesn't exist, 0 is returned. 216 | */ 217 | #define GetCoreDumpParameter(p, f) \ 218 | (CoreDumpParametersHas(p, f) ? (p)->f : 0) 219 | 220 | /* Clears the given coredumper parameters to zero, sets the size parameter and 221 | * the max_length parameter to SIZE_MAX. 222 | */ 223 | void ClearCoreDumpParametersInternal(struct CoreDumpParameters *params, 224 | size_t size); 225 | 226 | /* Sets the coredumper parameters to provide a limited core dump. Returns 227 | * zero on success otherwise -1 will be returned and errno will be set. 228 | */ 229 | int SetCoreDumpLimited(struct CoreDumpParameters *params, size_t max_length); 230 | 231 | /* Sets the coredumper parameters to provide a compressed core dump. Returns 232 | * zero on success otherwise -1 will be returned and errno will be set. 233 | */ 234 | int SetCoreDumpCompressed(struct CoreDumpParameters *params, 235 | const struct CoredumperCompressor *compressors, 236 | struct CoredumperCompressor **selected_compressor); 237 | 238 | /* Sets the coredumper parameters to provide a prioritized limited core file. 239 | * Returns zero on success otherwise -1 will be returned and errno will be set. 240 | */ 241 | int SetCoreDumpLimitedByPriority(struct CoreDumpParameters *params, 242 | size_t max_length); 243 | 244 | /* Sets the coredumper parameters to add extra notes to the core file. 245 | * Returns zero on success otherwise -1 will be returned and errno will be set. 246 | */ 247 | int SetCoreDumpNotes(struct CoreDumpParameters *params, 248 | struct CoredumperNote *notes, int note_count); 249 | 250 | #ifdef __cplusplus 251 | } 252 | #endif 253 | #endif /* _COREDUMP_H */ 254 | -------------------------------------------------------------------------------- /missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common stub for a few missing GNU programs while installing. 3 | 4 | scriptversion=2005-06-08.21 5 | 6 | # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 7 | # Free Software Foundation, Inc. 8 | # Originally by Fran,cois Pinard , 1996. 9 | 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2, or (at your option) 13 | # any later version. 14 | 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program; if not, write to the Free Software 22 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 23 | # 02110-1301, USA. 24 | 25 | # As a special exception to the GNU General Public License, if you 26 | # distribute this file as part of a program that contains a 27 | # configuration script generated by Autoconf, you may include it under 28 | # the same distribution terms that you use for the rest of that program. 29 | 30 | if test $# -eq 0; then 31 | echo 1>&2 "Try \`$0 --help' for more information" 32 | exit 1 33 | fi 34 | 35 | run=: 36 | 37 | # In the cases where this matters, `missing' is being run in the 38 | # srcdir already. 39 | if test -f configure.ac; then 40 | configure_ac=configure.ac 41 | else 42 | configure_ac=configure.in 43 | fi 44 | 45 | msg="missing on your system" 46 | 47 | case "$1" in 48 | --run) 49 | # Try to run requested program, and just exit if it succeeds. 50 | run= 51 | shift 52 | "$@" && exit 0 53 | # Exit code 63 means version mismatch. This often happens 54 | # when the user try to use an ancient version of a tool on 55 | # a file that requires a minimum version. In this case we 56 | # we should proceed has if the program had been absent, or 57 | # if --run hadn't been passed. 58 | if test $? = 63; then 59 | run=: 60 | msg="probably too old" 61 | fi 62 | ;; 63 | 64 | -h|--h|--he|--hel|--help) 65 | echo "\ 66 | $0 [OPTION]... PROGRAM [ARGUMENT]... 67 | 68 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an 69 | error status if there is no known handling for PROGRAM. 70 | 71 | Options: 72 | -h, --help display this help and exit 73 | -v, --version output version information and exit 74 | --run try to run the given command, and emulate it if it fails 75 | 76 | Supported PROGRAM values: 77 | aclocal touch file \`aclocal.m4' 78 | autoconf touch file \`configure' 79 | autoheader touch file \`config.h.in' 80 | automake touch all \`Makefile.in' files 81 | bison create \`y.tab.[ch]', if possible, from existing .[ch] 82 | flex create \`lex.yy.c', if possible, from existing .c 83 | help2man touch the output file 84 | lex create \`lex.yy.c', if possible, from existing .c 85 | makeinfo touch the output file 86 | tar try tar, gnutar, gtar, then tar without non-portable flags 87 | yacc create \`y.tab.[ch]', if possible, from existing .[ch] 88 | 89 | Send bug reports to ." 90 | exit $? 91 | ;; 92 | 93 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 94 | echo "missing $scriptversion (GNU Automake)" 95 | exit $? 96 | ;; 97 | 98 | -*) 99 | echo 1>&2 "$0: Unknown \`$1' option" 100 | echo 1>&2 "Try \`$0 --help' for more information" 101 | exit 1 102 | ;; 103 | 104 | esac 105 | 106 | # Now exit if we have it, but it failed. Also exit now if we 107 | # don't have it and --version was passed (most likely to detect 108 | # the program). 109 | case "$1" in 110 | lex|yacc) 111 | # Not GNU programs, they don't have --version. 112 | ;; 113 | 114 | tar) 115 | if test -n "$run"; then 116 | echo 1>&2 "ERROR: \`tar' requires --run" 117 | exit 1 118 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 119 | exit 1 120 | fi 121 | ;; 122 | 123 | *) 124 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 125 | # We have it, but it failed. 126 | exit 1 127 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 128 | # Could not run --version or --help. This is probably someone 129 | # running `$TOOL --version' or `$TOOL --help' to check whether 130 | # $TOOL exists and not knowing $TOOL uses missing. 131 | exit 1 132 | fi 133 | ;; 134 | esac 135 | 136 | # If it does not exist, or fails to run (possibly an outdated version), 137 | # try to emulate it. 138 | case "$1" in 139 | aclocal*) 140 | echo 1>&2 "\ 141 | WARNING: \`$1' is $msg. You should only need it if 142 | you modified \`acinclude.m4' or \`${configure_ac}'. You might want 143 | to install the \`Automake' and \`Perl' packages. Grab them from 144 | any GNU archive site." 145 | touch aclocal.m4 146 | ;; 147 | 148 | autoconf) 149 | echo 1>&2 "\ 150 | WARNING: \`$1' is $msg. You should only need it if 151 | you modified \`${configure_ac}'. You might want to install the 152 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU 153 | archive site." 154 | touch configure 155 | ;; 156 | 157 | autoheader) 158 | echo 1>&2 "\ 159 | WARNING: \`$1' is $msg. You should only need it if 160 | you modified \`acconfig.h' or \`${configure_ac}'. You might want 161 | to install the \`Autoconf' and \`GNU m4' packages. Grab them 162 | from any GNU archive site." 163 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` 164 | test -z "$files" && files="config.h" 165 | touch_files= 166 | for f in $files; do 167 | case "$f" in 168 | *:*) touch_files="$touch_files "`echo "$f" | 169 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; 170 | *) touch_files="$touch_files $f.in";; 171 | esac 172 | done 173 | touch $touch_files 174 | ;; 175 | 176 | automake*) 177 | echo 1>&2 "\ 178 | WARNING: \`$1' is $msg. You should only need it if 179 | you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. 180 | You might want to install the \`Automake' and \`Perl' packages. 181 | Grab them from any GNU archive site." 182 | find . -type f -name Makefile.am -print | 183 | sed 's/\.am$/.in/' | 184 | while read f; do touch "$f"; done 185 | ;; 186 | 187 | autom4te) 188 | echo 1>&2 "\ 189 | WARNING: \`$1' is needed, but is $msg. 190 | You might have modified some files without having the 191 | proper tools for further handling them. 192 | You can get \`$1' as part of \`Autoconf' from any GNU 193 | archive site." 194 | 195 | file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` 196 | test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` 197 | if test -f "$file"; then 198 | touch $file 199 | else 200 | test -z "$file" || exec >$file 201 | echo "#! /bin/sh" 202 | echo "# Created by GNU Automake missing as a replacement of" 203 | echo "# $ $@" 204 | echo "exit 0" 205 | chmod +x $file 206 | exit 1 207 | fi 208 | ;; 209 | 210 | bison|yacc) 211 | echo 1>&2 "\ 212 | WARNING: \`$1' $msg. You should only need it if 213 | you modified a \`.y' file. You may need the \`Bison' package 214 | in order for those modifications to take effect. You can get 215 | \`Bison' from any GNU archive site." 216 | rm -f y.tab.c y.tab.h 217 | if [ $# -ne 1 ]; then 218 | eval LASTARG="\${$#}" 219 | case "$LASTARG" in 220 | *.y) 221 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` 222 | if [ -f "$SRCFILE" ]; then 223 | cp "$SRCFILE" y.tab.c 224 | fi 225 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` 226 | if [ -f "$SRCFILE" ]; then 227 | cp "$SRCFILE" y.tab.h 228 | fi 229 | ;; 230 | esac 231 | fi 232 | if [ ! -f y.tab.h ]; then 233 | echo >y.tab.h 234 | fi 235 | if [ ! -f y.tab.c ]; then 236 | echo 'main() { return 0; }' >y.tab.c 237 | fi 238 | ;; 239 | 240 | lex|flex) 241 | echo 1>&2 "\ 242 | WARNING: \`$1' is $msg. You should only need it if 243 | you modified a \`.l' file. You may need the \`Flex' package 244 | in order for those modifications to take effect. You can get 245 | \`Flex' from any GNU archive site." 246 | rm -f lex.yy.c 247 | if [ $# -ne 1 ]; then 248 | eval LASTARG="\${$#}" 249 | case "$LASTARG" in 250 | *.l) 251 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` 252 | if [ -f "$SRCFILE" ]; then 253 | cp "$SRCFILE" lex.yy.c 254 | fi 255 | ;; 256 | esac 257 | fi 258 | if [ ! -f lex.yy.c ]; then 259 | echo 'main() { return 0; }' >lex.yy.c 260 | fi 261 | ;; 262 | 263 | help2man) 264 | echo 1>&2 "\ 265 | WARNING: \`$1' is $msg. You should only need it if 266 | you modified a dependency of a manual page. You may need the 267 | \`Help2man' package in order for those modifications to take 268 | effect. You can get \`Help2man' from any GNU archive site." 269 | 270 | file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` 271 | if test -z "$file"; then 272 | file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` 273 | fi 274 | if [ -f "$file" ]; then 275 | touch $file 276 | else 277 | test -z "$file" || exec >$file 278 | echo ".ab help2man is required to generate this page" 279 | exit 1 280 | fi 281 | ;; 282 | 283 | makeinfo) 284 | echo 1>&2 "\ 285 | WARNING: \`$1' is $msg. You should only need it if 286 | you modified a \`.texi' or \`.texinfo' file, or any other file 287 | indirectly affecting the aspect of the manual. The spurious 288 | call might also be the consequence of using a buggy \`make' (AIX, 289 | DU, IRIX). You might want to install the \`Texinfo' package or 290 | the \`GNU make' package. Grab either from any GNU archive site." 291 | # The file to touch is that specified with -o ... 292 | file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` 293 | if test -z "$file"; then 294 | # ... or it is the one specified with @setfilename ... 295 | infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` 296 | file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` 297 | # ... or it is derived from the source name (dir/f.texi becomes f.info) 298 | test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info 299 | fi 300 | # If the file does not exist, the user really needs makeinfo; 301 | # let's fail without touching anything. 302 | test -f $file || exit 1 303 | touch $file 304 | ;; 305 | 306 | tar) 307 | shift 308 | 309 | # We have already tried tar in the generic part. 310 | # Look for gnutar/gtar before invocation to avoid ugly error 311 | # messages. 312 | if (gnutar --version > /dev/null 2>&1); then 313 | gnutar "$@" && exit 0 314 | fi 315 | if (gtar --version > /dev/null 2>&1); then 316 | gtar "$@" && exit 0 317 | fi 318 | firstarg="$1" 319 | if shift; then 320 | case "$firstarg" in 321 | *o*) 322 | firstarg=`echo "$firstarg" | sed s/o//` 323 | tar "$firstarg" "$@" && exit 0 324 | ;; 325 | esac 326 | case "$firstarg" in 327 | *h*) 328 | firstarg=`echo "$firstarg" | sed s/h//` 329 | tar "$firstarg" "$@" && exit 0 330 | ;; 331 | esac 332 | fi 333 | 334 | echo 1>&2 "\ 335 | WARNING: I can't seem to be able to run \`tar' with the given arguments. 336 | You may want to install GNU tar or Free paxutils, or check the 337 | command line arguments." 338 | exit 1 339 | ;; 340 | 341 | *) 342 | echo 1>&2 "\ 343 | WARNING: \`$1' is needed, and is $msg. 344 | You might have modified some files without having the 345 | proper tools for further handling them. Check the \`README' file, 346 | it often tells you about the needed prerequisites for installing 347 | this package. You may also peek at any GNU archive site, in case 348 | some other package would contain this missing \`$1' program." 349 | exit 1 350 | ;; 351 | esac 352 | 353 | exit 0 354 | 355 | # Local variables: 356 | # eval: (add-hook 'write-file-hooks 'time-stamp) 357 | # time-stamp-start: "scriptversion=" 358 | # time-stamp-format: "%:y-%02m-%02d.%02H" 359 | # time-stamp-end: "$" 360 | # End: 361 | -------------------------------------------------------------------------------- /src/coredumper.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2008, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Markus Gutschke, Carl Crous 32 | * 33 | * Code to extract a core dump snapshot of the current process. 34 | */ 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "google/coredumper.h" 45 | #include "elfcore.h" 46 | #include "linux_syscall_support.h" 47 | #include "linuxthreads.h" 48 | #include "thread_lister.h" 49 | 50 | static const char *const no_args_bzip2[] = { "bzip2", NULL }; 51 | static const char *const no_args_gzip[] = { "gzip", NULL }; 52 | static const char *const no_args_compress[] = { "compress", NULL }; 53 | const struct CoredumperCompressor COREDUMPER_COMPRESSED[] = { 54 | { "/bin/bzip2", no_args_bzip2, ".bz2" }, 55 | { "/usr/bin/bzip2", no_args_bzip2, ".bz2" }, 56 | { "bzip2", no_args_bzip2, ".bz2" }, 57 | { "/bin/gzip", no_args_gzip, ".gz" }, 58 | { "/usr/bin/gzip", no_args_gzip, ".gz" }, 59 | { "gzip", no_args_gzip, ".gz" }, 60 | { "/bin/compress", no_args_compress, ".Z" }, 61 | { "/usr/bin/compress", no_args_compress, ".Z" }, 62 | { "compress", no_args_compress, ".Z" }, 63 | { "", 0, "" }, 64 | { 0, 0, 0 } }; 65 | const struct CoredumperCompressor COREDUMPER_BZIP2_COMPRESSED[] = { 66 | { "/bin/bzip2", no_args_bzip2, ".bz2" }, 67 | { "/usr/bin/bzip2", no_args_bzip2, ".bz2" }, 68 | { "bzip2", no_args_bzip2, ".bz2" }, 69 | { 0, 0, 0 } }; 70 | const struct CoredumperCompressor COREDUMPER_GZIP_COMPRESSED[] = { 71 | { "/bin/gzip", no_args_gzip, ".gz" }, 72 | { "/usr/bin/gzip", no_args_gzip, ".gz" }, 73 | { "gzip", no_args_gzip, ".gz" }, 74 | { 0, 0, 0 } }; 75 | const struct CoredumperCompressor COREDUMPER_COMPRESS_COMPRESSED[] = { 76 | { "/bin/compress", no_args_compress, ".Z" }, 77 | { "/usr/bin/compress", no_args_compress, ".Z" }, 78 | { "compress", no_args_compress, ".Z" }, 79 | { 0, 0, 0 } }; 80 | const struct CoredumperCompressor COREDUMPER_TRY_BZIP2_COMPRESSED[] = { 81 | { "/bin/bzip2", no_args_bzip2, ".bz2" }, 82 | { "/usr/bin/bzip2", no_args_bzip2, ".bz2" }, 83 | { "bzip2", no_args_bzip2, ".bz2" }, 84 | { "", 0, "" }, 85 | { 0, 0, 0 } }; 86 | const struct CoredumperCompressor COREDUMPER_TRY_GZIP_COMPRESSED[] = { 87 | { "/bin/gzip", no_args_gzip, ".gz" }, 88 | { "/usr/bin/gzip", no_args_gzip, ".gz" }, 89 | { "gzip", no_args_gzip, ".gz" }, 90 | { "", 0, "" }, 91 | { 0, 0, 0 } }; 92 | const struct CoredumperCompressor COREDUMPER_TRY_COMPRESS_COMPRESSED[] = { 93 | { "/bin/compress", no_args_compress, ".Z" }, 94 | { "/usr/bin/compress", no_args_compress, ".Z" }, 95 | { "compress", no_args_compress, ".Z" }, 96 | { "", 0, "" }, 97 | { 0, 0, 0 } }; 98 | const struct CoredumperCompressor COREDUMPER_UNCOMPRESSED[] = { 99 | { "", 0, "" }, 100 | { 0, 0, 0 } }; 101 | 102 | 103 | #ifndef DUMPER 104 | /* If the target platform lacks the necessary support for generating core dumps 105 | * on the fly, or if nobody has ported the code, then return an error. 106 | */ 107 | typedef void *Frame; 108 | #define FRAME(f) void *f = &&label; label: 109 | 110 | 111 | int InternalGetCoreDump(void *frame, int num_threads, pid_t *thread_pids, 112 | va_list ap) { 113 | errno = EINVAL; 114 | return -1; 115 | } 116 | #endif 117 | 118 | 119 | /* Internal helper method used by GetCoreDump(). 120 | */ 121 | static int GetCoreDumpFunction(void *frame, 122 | const struct CoreDumpParameters *params) { 123 | return ListAllProcessThreads(frame, InternalGetCoreDump, params, NULL, 124 | getenv("PATH")); 125 | } 126 | 127 | /* Returns a file handle that can be read to obtain a snapshot of the 128 | * current state of this process. If a core file could not be 129 | * generated for any reason, -1 is returned. 130 | * 131 | * This function momentarily suspends all threads, while creating a 132 | * COW copy of the process's address space. 133 | * 134 | * This function is neither reentrant nor async signal safe. Callers 135 | * should wrap a mutex around the invocation of this function, if necessary. 136 | * 137 | * The current implementation tries very hard to do behave reasonably when 138 | * called from a signal handler, but no guarantees are made that this will 139 | * always work. 140 | */ 141 | int GetCoreDump(void) { 142 | FRAME(frame); 143 | struct CoreDumpParameters params; 144 | ClearCoreDumpParameters(¶ms); 145 | return GetCoreDumpFunction(&frame, ¶ms); 146 | } 147 | 148 | int GetCoreDumpWith(const struct CoreDumpParameters *params) { 149 | FRAME(frame); 150 | if ((params->flags & COREDUMPER_FLAG_LIMITED) || 151 | (params->flags & COREDUMPER_FLAG_LIMITED_BY_PRIORITY)) { 152 | errno = EINVAL; 153 | return -1; 154 | } 155 | return GetCoreDumpFunction(&frame, params); 156 | } 157 | 158 | /* Attempts to compress the core file on the fly, if a suitable compressor 159 | * could be located. Sets "selected_compressor" to the compressor that 160 | * was picked. 161 | */ 162 | int GetCompressedCoreDump(const struct CoredumperCompressor compressors[], 163 | struct CoredumperCompressor **selected_compressor) { 164 | FRAME(frame); 165 | struct CoreDumpParameters params; 166 | ClearCoreDumpParameters(¶ms); 167 | SetCoreDumpCompressed(¶ms, compressors, selected_compressor); 168 | return GetCoreDumpFunction(&frame, ¶ms); 169 | } 170 | 171 | /* Re-runs fn until it doesn't cause EINTR. 172 | */ 173 | #define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR) 174 | 175 | 176 | /* Internal helper method used by WriteCoreDump(). 177 | */ 178 | static int WriteCoreDumpFunction(void *frame, 179 | const struct CoreDumpParameters *params, 180 | const char *file_name) { 181 | return ListAllProcessThreads(frame, InternalGetCoreDump, params, file_name, 182 | getenv("PATH")); 183 | } 184 | 185 | /* Writes the core file to disk. This is a convenience method wrapping 186 | * GetCoreDump(). If a core file could not be generated for any reason, 187 | * -1 is returned. On success, zero is returned. 188 | */ 189 | int WriteCoreDump(const char *file_name) { 190 | FRAME(frame); 191 | struct CoreDumpParameters params; 192 | ClearCoreDumpParameters(¶ms); 193 | return WriteCoreDumpFunction(&frame, ¶ms, file_name); 194 | } 195 | 196 | int WriteCoreDumpWith(const struct CoreDumpParameters *params, 197 | const char *file_name) { 198 | FRAME(frame); 199 | return WriteCoreDumpFunction(&frame, params, file_name); 200 | } 201 | 202 | /* Callers might need to restrict the maximum size of the core file. This 203 | * convenience method provides the necessary support to emulate "ulimit -c". 204 | */ 205 | int WriteCoreDumpLimited(const char *file_name, size_t max_length) { 206 | FRAME(frame); 207 | struct CoreDumpParameters params; 208 | ClearCoreDumpParameters(¶ms); 209 | SetCoreDumpLimited(¶ms, max_length); 210 | return WriteCoreDumpFunction(&frame, ¶ms, file_name); 211 | } 212 | 213 | /* This will limit the size of the core file by reducing or removing the 214 | * largest memory segments first, effectively prioritizing the smaller memory 215 | * segments. This behavior is preferred when the process has a large heap and 216 | * you would like to preserve the relatively small stack. 217 | */ 218 | int WriteCoreDumpLimitedByPriority(const char *file_name, size_t max_length) { 219 | FRAME(frame); 220 | struct CoreDumpParameters params; 221 | ClearCoreDumpParameters(¶ms); 222 | SetCoreDumpLimitedByPriority(¶ms, max_length); 223 | return WriteCoreDumpFunction(&frame, ¶ms, file_name); 224 | } 225 | 226 | /* Attempts to compress the core file on the fly, if a suitable compressor 227 | * could be located. Sets "selected_compressor" to the compressor that 228 | * was picked. The filename automatically has a suitable suffix appended 229 | * to it. Normally this would be ".bz2" for bzip2 compression ".gz" for 230 | * gzip compression, or ".Z" for compress compression. This behavior can 231 | * be changed by defining custom CoredumperCompressor descriptions. 232 | */ 233 | int WriteCompressedCoreDump(const char *file_name, size_t max_length, 234 | const struct CoredumperCompressor compressors[], 235 | struct CoredumperCompressor **selected_compressor){ 236 | FRAME(frame); 237 | struct CoreDumpParameters params; 238 | ClearCoreDumpParameters(¶ms); 239 | SetCoreDumpCompressed(¶ms, compressors, selected_compressor); 240 | SetCoreDumpLimited(¶ms, max_length); 241 | return WriteCoreDumpFunction(&frame, ¶ms, file_name); 242 | } 243 | 244 | void ClearCoreDumpParametersInternal(struct CoreDumpParameters *params, 245 | size_t size) { 246 | memset(params, 0, size); 247 | params->size = size; 248 | SetCoreDumpParameter(params, max_length, SIZE_MAX); 249 | } 250 | 251 | int SetCoreDumpLimited(struct CoreDumpParameters *params, size_t max_length) { 252 | if (params->flags & COREDUMPER_FLAG_LIMITED_BY_PRIORITY) { 253 | errno = EINVAL; 254 | return -1; 255 | } 256 | params->flags |= COREDUMPER_FLAG_LIMITED; 257 | SetCoreDumpParameter(params, max_length, max_length); 258 | return 0; 259 | } 260 | 261 | int SetCoreDumpCompressed(struct CoreDumpParameters *params, 262 | const struct CoredumperCompressor *compressors, 263 | struct CoredumperCompressor **selected_compressor) { 264 | if (params->flags & COREDUMPER_FLAG_LIMITED_BY_PRIORITY) { 265 | errno = EINVAL; 266 | return -1; 267 | } 268 | SetCoreDumpParameter(params, compressors, compressors); 269 | SetCoreDumpParameter(params, selected_compressor, selected_compressor); 270 | return 0; 271 | } 272 | 273 | int SetCoreDumpLimitedByPriority(struct CoreDumpParameters *params, 274 | size_t max_length) { 275 | if (((params->flags & COREDUMPER_FLAG_LIMITED) && 276 | !(params->flags & COREDUMPER_FLAG_LIMITED_BY_PRIORITY)) || 277 | params->compressors != NULL) { 278 | errno = EINVAL; 279 | return -1; 280 | } 281 | SetCoreDumpParameter(params, flags, params->flags | 282 | COREDUMPER_FLAG_LIMITED | 283 | COREDUMPER_FLAG_LIMITED_BY_PRIORITY); 284 | SetCoreDumpParameter(params, max_length, max_length); 285 | return 0; 286 | } 287 | 288 | int SetCoreDumpNotes(struct CoreDumpParameters *params, 289 | struct CoredumperNote *notes, int note_count) { 290 | SetCoreDumpParameter(params, notes, notes); 291 | SetCoreDumpParameter(params, note_count, note_count); 292 | return 0; 293 | } 294 | -------------------------------------------------------------------------------- /src/linux_syscall_support_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2007-2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // --- 31 | // Author: Markus Gutschke 32 | 33 | // Include linux_syscall_support.h as the first file, so we will compilation 34 | // errors if it has unexpected dependencies on other header files. 35 | #include "linux_syscall_support.h" 36 | 37 | #include 38 | 39 | // Used to count the number of check failures 40 | static int check_failures = 0; 41 | 42 | #define CHECK(cond) do { \ 43 | if (!(cond)) { \ 44 | puts("Check failed: " #cond); \ 45 | ++check_failures; \ 46 | } \ 47 | } while (0) 48 | 49 | 50 | // We need to do some "namespace" magic to be able to include both 51 | // and , which normally are mutually exclusive. 52 | // This is currently the only reason why this test has to be compiled as 53 | // C++ code. 54 | namespace linux_syscall_support { 55 | #include 56 | } 57 | #include 58 | 59 | namespace linux_syscall_support { 60 | // Define kernel data structures as known to glibc 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | 73 | // Set by the signal handler to show that we received a signal 74 | static int signaled; 75 | 76 | static void CheckStructures() { 77 | puts("CheckStructures..."); 78 | // Compare sizes of the kernel structures. This will allow us to 79 | // catch cases where linux_syscall_support.h defined structures that 80 | // are obviously different from the ones the kernel expects. This is 81 | // a little complicated, because glibc often deliberately defines 82 | // incompatible versions. We address this issue on a case-by-case 83 | // basis by including the appropriate linux-specific header files 84 | // within our own namespace, instead of within the global 85 | // namespace. Occasionally, this requires careful sorting of header 86 | // files, too (e.g. in the case of "stat.h"). And we provide cleanup 87 | // where necessary (e.g. in the case of "struct statfs"). This is 88 | // far from perfect, but in the worst case, it'll lead to false 89 | // error messages that need to be fixed manually. Unfortunately, 90 | // there are a small number of data structures (e.g "struct 91 | // kernel_old_sigaction") that we cannot test at all, as glibc does 92 | // not have any definitions for them. 93 | CHECK(sizeof(struct iovec) == sizeof(struct kernel_iovec)); 94 | CHECK(sizeof(struct msghdr) == sizeof(struct kernel_msghdr)); 95 | CHECK(sizeof(struct pollfd) == sizeof(struct kernel_pollfd)); 96 | CHECK(sizeof(struct rlimit) == sizeof(struct kernel_rlimit)); 97 | CHECK(sizeof(struct rusage) == sizeof(struct kernel_rusage)); 98 | CHECK(sizeof(struct sigaction) == sizeof(struct kernel_sigaction) 99 | // glibc defines an excessively large sigset_t. Compensate for it: 100 | + sizeof(((struct sigaction *)0)->sa_mask) - KERNEL_NSIG/8 101 | #ifdef __mips__ 102 | + 2*sizeof(int) 103 | #endif 104 | ); 105 | CHECK(sizeof(struct sockaddr) == sizeof(struct kernel_sockaddr)); 106 | CHECK(sizeof(struct stat) == sizeof(struct kernel_stat)); 107 | CHECK(sizeof(struct statfs) == sizeof(struct kernel_statfs) 108 | #ifdef __USE_FILE_OFFSET64 109 | // glibc sometimes defines 64-bit wide fields in "struct statfs" 110 | // even though this is just the 32-bit version of the structure. 111 | + 5*(sizeof(((struct statfs *)0)->f_blocks) - sizeof(unsigned)) 112 | #endif 113 | ); 114 | CHECK(sizeof(struct timespec) == sizeof(struct kernel_timespec)); 115 | #ifndef __x86_64__ 116 | CHECK(sizeof(struct stat64) == sizeof(struct kernel_stat64)); 117 | CHECK(sizeof(struct statfs64) == sizeof(struct kernel_statfs64)); 118 | #endif 119 | } 120 | 121 | #ifdef __mips__ 122 | #define ZERO_SIGACT { 0 } 123 | #else 124 | #define ZERO_SIGACT { { 0 } } 125 | #endif 126 | 127 | static void SigHandler(int signum) { 128 | if (signaled) { 129 | // Caller will report an error, as we cannot do so from a signal handler 130 | signaled = -1; 131 | } else { 132 | signaled = signum; 133 | } 134 | return; 135 | } 136 | 137 | static void SigAction(int signum, struct siginfo *si, void *arg) { 138 | SigHandler(signum); 139 | } 140 | 141 | static void Sigaction() { 142 | puts("Sigaction..."); 143 | int signum = SIGPWR; 144 | for (int info = 0; info < 2; info++) { 145 | signaled = 0; 146 | struct kernel_sigaction sa = ZERO_SIGACT, old, orig; 147 | CHECK(!sys_sigaction(signum, NULL, &orig)); 148 | if (info) { 149 | sa.sa_sigaction_ = SigAction; 150 | } else { 151 | sa.sa_handler_ = SigHandler; 152 | } 153 | sa.sa_flags = SA_RESETHAND | SA_RESTART | (info ? SA_SIGINFO : 0); 154 | CHECK(!sys_sigemptyset(&sa.sa_mask)); 155 | CHECK(!sys_sigaction(signum, &sa, &old)); 156 | CHECK(!memcmp(&old, &orig, sizeof(struct kernel_sigaction))); 157 | CHECK(!sys_sigaction(signum, NULL, &old)); 158 | #if defined(__i386__) || defined(__x86_64__) 159 | old.sa_restorer = sa.sa_restorer; 160 | old.sa_flags &= ~SA_RESTORER; 161 | #endif 162 | CHECK(!memcmp(&old, &sa, sizeof(struct kernel_sigaction))); 163 | struct kernel_sigset_t pending; 164 | CHECK(!sys_sigpending(&pending)); 165 | CHECK(!sys_sigismember(&pending, signum)); 166 | struct kernel_sigset_t mask, oldmask; 167 | CHECK(!sys_sigemptyset(&mask)); 168 | CHECK(!sys_sigaddset(&mask, signum)); 169 | CHECK(!sys_sigprocmask(SIG_BLOCK, &mask, &oldmask)); 170 | CHECK(!sys_kill(sys_getpid(), signum)); 171 | CHECK(!sys_sigpending(&pending)); 172 | CHECK(sys_sigismember(&pending, signum)); 173 | CHECK(!signaled); 174 | CHECK(!sys_sigfillset(&mask)); 175 | CHECK(!sys_sigdelset(&mask, signum)); 176 | CHECK(sys_sigsuspend(&mask) == -1); 177 | CHECK(signaled == signum); 178 | CHECK(!sys_sigaction(signum, &orig, NULL)); 179 | CHECK(!sys_sigprocmask(SIG_SETMASK, &oldmask, NULL)); 180 | } 181 | } 182 | 183 | static void OldSigaction() { 184 | #if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__PPC__) || \ 185 | (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) 186 | puts("OldSigaction..."); 187 | int signum = SIGPWR; 188 | for (int info = 0; info < 2; info++) { 189 | signaled = 0; 190 | struct kernel_old_sigaction sa = ZERO_SIGACT, old, orig; 191 | CHECK(!sys__sigaction(signum, NULL, &orig)); 192 | if (info) { 193 | sa.sa_sigaction_ = SigAction; 194 | } else { 195 | sa.sa_handler_ = SigHandler; 196 | } 197 | sa.sa_flags = SA_RESETHAND | SA_RESTART | (info ? SA_SIGINFO : 0); 198 | memset(&sa.sa_mask, 0, sizeof(sa.sa_mask)); 199 | CHECK(!sys__sigaction(signum, &sa, &old)); 200 | CHECK(!memcmp(&old, &orig, sizeof(struct kernel_old_sigaction))); 201 | CHECK(!sys__sigaction(signum, NULL, &old)); 202 | #ifndef __mips__ 203 | old.sa_restorer = sa.sa_restorer; 204 | #endif 205 | CHECK(!memcmp(&old, &sa, sizeof(struct kernel_old_sigaction))); 206 | unsigned long pending; 207 | CHECK(!sys__sigpending(&pending)); 208 | CHECK(!(pending & (1UL << (signum - 1)))); 209 | unsigned long mask, oldmask; 210 | mask = 1 << (signum - 1); 211 | CHECK(!sys__sigprocmask(SIG_BLOCK, &mask, &oldmask)); 212 | CHECK(!sys_kill(sys_getpid(), signum)); 213 | CHECK(!sys__sigpending(&pending)); 214 | CHECK(pending & (1UL << (signum - 1))); 215 | CHECK(!signaled); 216 | mask = ~mask; 217 | CHECK(sys__sigsuspend( 218 | #ifndef __PPC__ 219 | &mask, 0, 220 | #endif 221 | mask) == -1); 222 | CHECK(signaled == signum); 223 | CHECK(!sys__sigaction(signum, &orig, NULL)); 224 | CHECK(!sys__sigprocmask(SIG_SETMASK, &oldmask, NULL)); 225 | } 226 | #endif 227 | } 228 | 229 | templatestatic void AlmostEquals(A a, B b) { 230 | double d = 0.0 + a - b; 231 | if (d < 0) { 232 | d = -d; 233 | } 234 | double avg = a/2.0 + b/2.0; 235 | if (avg < 4096) { 236 | // Round up to a minimum size. Otherwise, even minute changes could 237 | // trigger a false positive. 238 | avg = 4096; 239 | } 240 | // Check that a and b are within one percent of each other. 241 | CHECK(d / avg < 0.01); 242 | } 243 | 244 | static void StatFs() { 245 | puts("StatFs..."); 246 | struct statfs64 libc_statfs; 247 | struct kernel_statfs kernel_statfs; 248 | CHECK(!statfs64("/", &libc_statfs)); 249 | CHECK(!sys_statfs("/", &kernel_statfs)); 250 | CHECK(libc_statfs.f_type == kernel_statfs.f_type); 251 | CHECK(libc_statfs.f_bsize == kernel_statfs.f_bsize); 252 | CHECK(libc_statfs.f_blocks == kernel_statfs.f_blocks); 253 | AlmostEquals(libc_statfs.f_bfree, kernel_statfs.f_bfree); 254 | AlmostEquals(libc_statfs.f_bavail, kernel_statfs.f_bavail); 255 | CHECK(libc_statfs.f_files == kernel_statfs.f_files); 256 | AlmostEquals(libc_statfs.f_ffree, kernel_statfs.f_ffree); 257 | CHECK(libc_statfs.f_fsid.__val[0] == kernel_statfs.f_fsid.val[0]); 258 | CHECK(libc_statfs.f_fsid.__val[1] == kernel_statfs.f_fsid.val[1]); 259 | CHECK(libc_statfs.f_namelen == kernel_statfs.f_namelen); 260 | } 261 | 262 | static void StatFs64() { 263 | #if defined(__i386__) || defined(__ARM_ARCH_3__) || \ 264 | (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64) 265 | puts("StatFs64..."); 266 | struct statfs64 libc_statfs; 267 | struct kernel_statfs64 kernel_statfs; 268 | CHECK(!statfs64("/", &libc_statfs)); 269 | CHECK(!sys_statfs64("/", &kernel_statfs)); 270 | CHECK(libc_statfs.f_type == kernel_statfs.f_type); 271 | CHECK(libc_statfs.f_bsize == kernel_statfs.f_bsize); 272 | CHECK(libc_statfs.f_blocks == kernel_statfs.f_blocks); 273 | AlmostEquals(libc_statfs.f_bfree, kernel_statfs.f_bfree); 274 | AlmostEquals(libc_statfs.f_bavail, kernel_statfs.f_bavail); 275 | CHECK(libc_statfs.f_files == kernel_statfs.f_files); 276 | AlmostEquals(libc_statfs.f_ffree, kernel_statfs.f_ffree); 277 | CHECK(libc_statfs.f_fsid.__val[0] == kernel_statfs.f_fsid.val[0]); 278 | CHECK(libc_statfs.f_fsid.__val[1] == kernel_statfs.f_fsid.val[1]); 279 | CHECK(libc_statfs.f_namelen == kernel_statfs.f_namelen); 280 | #endif 281 | } 282 | 283 | static void Stat() { 284 | static const char * const entries[] = { "/dev/null", "/bin/sh", "/", NULL }; 285 | puts("Stat..."); 286 | for (int i = 0; entries[i]; i++) { 287 | struct ::stat64 libc_stat; 288 | struct kernel_stat kernel_stat; 289 | CHECK(!::stat64(entries[i], &libc_stat)); 290 | CHECK(!sys_stat(entries[i], &kernel_stat)); 291 | // CHECK(libc_stat.st_dev == kernel_stat.st_dev); 292 | CHECK(libc_stat.st_ino == kernel_stat.st_ino); 293 | CHECK(libc_stat.st_mode == kernel_stat.st_mode); 294 | CHECK(libc_stat.st_nlink == kernel_stat.st_nlink); 295 | CHECK(libc_stat.st_uid == kernel_stat.st_uid); 296 | CHECK(libc_stat.st_gid == kernel_stat.st_gid); 297 | CHECK(libc_stat.st_rdev == kernel_stat.st_rdev); 298 | CHECK(libc_stat.st_size == kernel_stat.st_size); 299 | #if !defined(__i386__) && !defined(__ARM_ARCH_3__) && !defined(__PPC__) && \ 300 | !(defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64) 301 | CHECK(libc_stat.st_blksize == kernel_stat.st_blksize); 302 | CHECK(libc_stat.st_blocks == kernel_stat.st_blocks); 303 | #endif 304 | CHECK(libc_stat.st_atime == kernel_stat.st_atime_); 305 | CHECK(libc_stat.st_mtime == kernel_stat.st_mtime_); 306 | CHECK(libc_stat.st_ctime == kernel_stat.st_ctime_); 307 | } 308 | } 309 | 310 | static void Stat64() { 311 | #if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__PPC__) || \ 312 | (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64) 313 | puts("Stat64..."); 314 | static const char * const entries[] = { "/dev/null", "/bin/sh", "/", NULL }; 315 | for (int i = 0; entries[i]; i++) { 316 | struct ::stat64 libc_stat; 317 | struct kernel_stat64 kernel_stat; 318 | CHECK(!::stat64(entries[i], &libc_stat)); 319 | CHECK(!sys_stat64(entries[i], &kernel_stat)); 320 | CHECK(libc_stat.st_dev == kernel_stat.st_dev); 321 | CHECK(libc_stat.st_ino == kernel_stat.st_ino); 322 | CHECK(libc_stat.st_mode == kernel_stat.st_mode); 323 | CHECK(libc_stat.st_nlink == kernel_stat.st_nlink); 324 | CHECK(libc_stat.st_uid == kernel_stat.st_uid); 325 | CHECK(libc_stat.st_gid == kernel_stat.st_gid); 326 | CHECK(libc_stat.st_rdev == kernel_stat.st_rdev); 327 | CHECK(libc_stat.st_size == kernel_stat.st_size); 328 | CHECK(libc_stat.st_blksize == kernel_stat.st_blksize); 329 | CHECK(libc_stat.st_blocks == kernel_stat.st_blocks); 330 | CHECK(libc_stat.st_atime == kernel_stat.st_atime_); 331 | CHECK(libc_stat.st_mtime == kernel_stat.st_mtime_); 332 | CHECK(libc_stat.st_ctime == kernel_stat.st_ctime_); 333 | } 334 | #endif 335 | } 336 | 337 | } // namespace 338 | 339 | int main(int argc, char *argv[]) { 340 | linux_syscall_support::CheckStructures(); 341 | linux_syscall_support::Sigaction(); 342 | linux_syscall_support::OldSigaction(); 343 | linux_syscall_support::StatFs(); 344 | linux_syscall_support::StatFs64(); 345 | linux_syscall_support::Stat(); 346 | linux_syscall_support::Stat64(); 347 | 348 | if (check_failures == 0) 349 | puts("PASS"); 350 | else 351 | puts("FAIL"); 352 | return check_failures; 353 | } 354 | -------------------------------------------------------------------------------- /depcomp: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # depcomp - compile a program generating dependencies as side-effects 3 | 4 | scriptversion=2005-07-09.11 5 | 6 | # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. 7 | 8 | # This program is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2, or (at your option) 11 | # any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program; if not, write to the Free Software 20 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 21 | # 02110-1301, USA. 22 | 23 | # As a special exception to the GNU General Public License, if you 24 | # distribute this file as part of a program that contains a 25 | # configuration script generated by Autoconf, you may include it under 26 | # the same distribution terms that you use for the rest of that program. 27 | 28 | # Originally written by Alexandre Oliva . 29 | 30 | case $1 in 31 | '') 32 | echo "$0: No command. Try \`$0 --help' for more information." 1>&2 33 | exit 1; 34 | ;; 35 | -h | --h*) 36 | cat <<\EOF 37 | Usage: depcomp [--help] [--version] PROGRAM [ARGS] 38 | 39 | Run PROGRAMS ARGS to compile a file, generating dependencies 40 | as side-effects. 41 | 42 | Environment variables: 43 | depmode Dependency tracking mode. 44 | source Source file read by `PROGRAMS ARGS'. 45 | object Object file output by `PROGRAMS ARGS'. 46 | DEPDIR directory where to store dependencies. 47 | depfile Dependency file to output. 48 | tmpdepfile Temporary file to use when outputing dependencies. 49 | libtool Whether libtool is used (yes/no). 50 | 51 | Report bugs to . 52 | EOF 53 | exit $? 54 | ;; 55 | -v | --v*) 56 | echo "depcomp $scriptversion" 57 | exit $? 58 | ;; 59 | esac 60 | 61 | if test -z "$depmode" || test -z "$source" || test -z "$object"; then 62 | echo "depcomp: Variables source, object and depmode must be set" 1>&2 63 | exit 1 64 | fi 65 | 66 | # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. 67 | depfile=${depfile-`echo "$object" | 68 | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} 69 | tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} 70 | 71 | rm -f "$tmpdepfile" 72 | 73 | # Some modes work just like other modes, but use different flags. We 74 | # parameterize here, but still list the modes in the big case below, 75 | # to make depend.m4 easier to write. Note that we *cannot* use a case 76 | # here, because this file can only contain one case statement. 77 | if test "$depmode" = hp; then 78 | # HP compiler uses -M and no extra arg. 79 | gccflag=-M 80 | depmode=gcc 81 | fi 82 | 83 | if test "$depmode" = dashXmstdout; then 84 | # This is just like dashmstdout with a different argument. 85 | dashmflag=-xM 86 | depmode=dashmstdout 87 | fi 88 | 89 | case "$depmode" in 90 | gcc3) 91 | ## gcc 3 implements dependency tracking that does exactly what 92 | ## we want. Yay! Note: for some reason libtool 1.4 doesn't like 93 | ## it if -MD -MP comes after the -MF stuff. Hmm. 94 | "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" 95 | stat=$? 96 | if test $stat -eq 0; then : 97 | else 98 | rm -f "$tmpdepfile" 99 | exit $stat 100 | fi 101 | mv "$tmpdepfile" "$depfile" 102 | ;; 103 | 104 | gcc) 105 | ## There are various ways to get dependency output from gcc. Here's 106 | ## why we pick this rather obscure method: 107 | ## - Don't want to use -MD because we'd like the dependencies to end 108 | ## up in a subdir. Having to rename by hand is ugly. 109 | ## (We might end up doing this anyway to support other compilers.) 110 | ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like 111 | ## -MM, not -M (despite what the docs say). 112 | ## - Using -M directly means running the compiler twice (even worse 113 | ## than renaming). 114 | if test -z "$gccflag"; then 115 | gccflag=-MD, 116 | fi 117 | "$@" -Wp,"$gccflag$tmpdepfile" 118 | stat=$? 119 | if test $stat -eq 0; then : 120 | else 121 | rm -f "$tmpdepfile" 122 | exit $stat 123 | fi 124 | rm -f "$depfile" 125 | echo "$object : \\" > "$depfile" 126 | alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 127 | ## The second -e expression handles DOS-style file names with drive letters. 128 | sed -e 's/^[^:]*: / /' \ 129 | -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" 130 | ## This next piece of magic avoids the `deleted header file' problem. 131 | ## The problem is that when a header file which appears in a .P file 132 | ## is deleted, the dependency causes make to die (because there is 133 | ## typically no way to rebuild the header). We avoid this by adding 134 | ## dummy dependencies for each header file. Too bad gcc doesn't do 135 | ## this for us directly. 136 | tr ' ' ' 137 | ' < "$tmpdepfile" | 138 | ## Some versions of gcc put a space before the `:'. On the theory 139 | ## that the space means something, we add a space to the output as 140 | ## well. 141 | ## Some versions of the HPUX 10.20 sed can't process this invocation 142 | ## correctly. Breaking it into two sed invocations is a workaround. 143 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 144 | rm -f "$tmpdepfile" 145 | ;; 146 | 147 | hp) 148 | # This case exists only to let depend.m4 do its work. It works by 149 | # looking at the text of this script. This case will never be run, 150 | # since it is checked for above. 151 | exit 1 152 | ;; 153 | 154 | sgi) 155 | if test "$libtool" = yes; then 156 | "$@" "-Wp,-MDupdate,$tmpdepfile" 157 | else 158 | "$@" -MDupdate "$tmpdepfile" 159 | fi 160 | stat=$? 161 | if test $stat -eq 0; then : 162 | else 163 | rm -f "$tmpdepfile" 164 | exit $stat 165 | fi 166 | rm -f "$depfile" 167 | 168 | if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files 169 | echo "$object : \\" > "$depfile" 170 | 171 | # Clip off the initial element (the dependent). Don't try to be 172 | # clever and replace this with sed code, as IRIX sed won't handle 173 | # lines with more than a fixed number of characters (4096 in 174 | # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; 175 | # the IRIX cc adds comments like `#:fec' to the end of the 176 | # dependency line. 177 | tr ' ' ' 178 | ' < "$tmpdepfile" \ 179 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ 180 | tr ' 181 | ' ' ' >> $depfile 182 | echo >> $depfile 183 | 184 | # The second pass generates a dummy entry for each header file. 185 | tr ' ' ' 186 | ' < "$tmpdepfile" \ 187 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ 188 | >> $depfile 189 | else 190 | # The sourcefile does not contain any dependencies, so just 191 | # store a dummy comment line, to avoid errors with the Makefile 192 | # "include basename.Plo" scheme. 193 | echo "#dummy" > "$depfile" 194 | fi 195 | rm -f "$tmpdepfile" 196 | ;; 197 | 198 | aix) 199 | # The C for AIX Compiler uses -M and outputs the dependencies 200 | # in a .u file. In older versions, this file always lives in the 201 | # current directory. Also, the AIX compiler puts `$object:' at the 202 | # start of each line; $object doesn't have directory information. 203 | # Version 6 uses the directory in both cases. 204 | stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` 205 | tmpdepfile="$stripped.u" 206 | if test "$libtool" = yes; then 207 | "$@" -Wc,-M 208 | else 209 | "$@" -M 210 | fi 211 | stat=$? 212 | 213 | if test -f "$tmpdepfile"; then : 214 | else 215 | stripped=`echo "$stripped" | sed 's,^.*/,,'` 216 | tmpdepfile="$stripped.u" 217 | fi 218 | 219 | if test $stat -eq 0; then : 220 | else 221 | rm -f "$tmpdepfile" 222 | exit $stat 223 | fi 224 | 225 | if test -f "$tmpdepfile"; then 226 | outname="$stripped.o" 227 | # Each line is of the form `foo.o: dependent.h'. 228 | # Do two passes, one to just change these to 229 | # `$object: dependent.h' and one to simply `dependent.h:'. 230 | sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" 231 | sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" 232 | else 233 | # The sourcefile does not contain any dependencies, so just 234 | # store a dummy comment line, to avoid errors with the Makefile 235 | # "include basename.Plo" scheme. 236 | echo "#dummy" > "$depfile" 237 | fi 238 | rm -f "$tmpdepfile" 239 | ;; 240 | 241 | icc) 242 | # Intel's C compiler understands `-MD -MF file'. However on 243 | # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c 244 | # ICC 7.0 will fill foo.d with something like 245 | # foo.o: sub/foo.c 246 | # foo.o: sub/foo.h 247 | # which is wrong. We want: 248 | # sub/foo.o: sub/foo.c 249 | # sub/foo.o: sub/foo.h 250 | # sub/foo.c: 251 | # sub/foo.h: 252 | # ICC 7.1 will output 253 | # foo.o: sub/foo.c sub/foo.h 254 | # and will wrap long lines using \ : 255 | # foo.o: sub/foo.c ... \ 256 | # sub/foo.h ... \ 257 | # ... 258 | 259 | "$@" -MD -MF "$tmpdepfile" 260 | stat=$? 261 | if test $stat -eq 0; then : 262 | else 263 | rm -f "$tmpdepfile" 264 | exit $stat 265 | fi 266 | rm -f "$depfile" 267 | # Each line is of the form `foo.o: dependent.h', 268 | # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. 269 | # Do two passes, one to just change these to 270 | # `$object: dependent.h' and one to simply `dependent.h:'. 271 | sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" 272 | # Some versions of the HPUX 10.20 sed can't process this invocation 273 | # correctly. Breaking it into two sed invocations is a workaround. 274 | sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | 275 | sed -e 's/$/ :/' >> "$depfile" 276 | rm -f "$tmpdepfile" 277 | ;; 278 | 279 | tru64) 280 | # The Tru64 compiler uses -MD to generate dependencies as a side 281 | # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. 282 | # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 283 | # dependencies in `foo.d' instead, so we check for that too. 284 | # Subdirectories are respected. 285 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 286 | test "x$dir" = "x$object" && dir= 287 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 288 | 289 | if test "$libtool" = yes; then 290 | # With Tru64 cc, shared objects can also be used to make a 291 | # static library. This mecanism is used in libtool 1.4 series to 292 | # handle both shared and static libraries in a single compilation. 293 | # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. 294 | # 295 | # With libtool 1.5 this exception was removed, and libtool now 296 | # generates 2 separate objects for the 2 libraries. These two 297 | # compilations output dependencies in in $dir.libs/$base.o.d and 298 | # in $dir$base.o.d. We have to check for both files, because 299 | # one of the two compilations can be disabled. We should prefer 300 | # $dir$base.o.d over $dir.libs/$base.o.d because the latter is 301 | # automatically cleaned when .libs/ is deleted, while ignoring 302 | # the former would cause a distcleancheck panic. 303 | tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 304 | tmpdepfile2=$dir$base.o.d # libtool 1.5 305 | tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 306 | tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 307 | "$@" -Wc,-MD 308 | else 309 | tmpdepfile1=$dir$base.o.d 310 | tmpdepfile2=$dir$base.d 311 | tmpdepfile3=$dir$base.d 312 | tmpdepfile4=$dir$base.d 313 | "$@" -MD 314 | fi 315 | 316 | stat=$? 317 | if test $stat -eq 0; then : 318 | else 319 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" 320 | exit $stat 321 | fi 322 | 323 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" 324 | do 325 | test -f "$tmpdepfile" && break 326 | done 327 | if test -f "$tmpdepfile"; then 328 | sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" 329 | # That's a tab and a space in the []. 330 | sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" 331 | else 332 | echo "#dummy" > "$depfile" 333 | fi 334 | rm -f "$tmpdepfile" 335 | ;; 336 | 337 | #nosideeffect) 338 | # This comment above is used by automake to tell side-effect 339 | # dependency tracking mechanisms from slower ones. 340 | 341 | dashmstdout) 342 | # Important note: in order to support this mode, a compiler *must* 343 | # always write the preprocessed file to stdout, regardless of -o. 344 | "$@" || exit $? 345 | 346 | # Remove the call to Libtool. 347 | if test "$libtool" = yes; then 348 | while test $1 != '--mode=compile'; do 349 | shift 350 | done 351 | shift 352 | fi 353 | 354 | # Remove `-o $object'. 355 | IFS=" " 356 | for arg 357 | do 358 | case $arg in 359 | -o) 360 | shift 361 | ;; 362 | $object) 363 | shift 364 | ;; 365 | *) 366 | set fnord "$@" "$arg" 367 | shift # fnord 368 | shift # $arg 369 | ;; 370 | esac 371 | done 372 | 373 | test -z "$dashmflag" && dashmflag=-M 374 | # Require at least two characters before searching for `:' 375 | # in the target name. This is to cope with DOS-style filenames: 376 | # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. 377 | "$@" $dashmflag | 378 | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" 379 | rm -f "$depfile" 380 | cat < "$tmpdepfile" > "$depfile" 381 | tr ' ' ' 382 | ' < "$tmpdepfile" | \ 383 | ## Some versions of the HPUX 10.20 sed can't process this invocation 384 | ## correctly. Breaking it into two sed invocations is a workaround. 385 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 386 | rm -f "$tmpdepfile" 387 | ;; 388 | 389 | dashXmstdout) 390 | # This case only exists to satisfy depend.m4. It is never actually 391 | # run, as this mode is specially recognized in the preamble. 392 | exit 1 393 | ;; 394 | 395 | makedepend) 396 | "$@" || exit $? 397 | # Remove any Libtool call 398 | if test "$libtool" = yes; then 399 | while test $1 != '--mode=compile'; do 400 | shift 401 | done 402 | shift 403 | fi 404 | # X makedepend 405 | shift 406 | cleared=no 407 | for arg in "$@"; do 408 | case $cleared in 409 | no) 410 | set ""; shift 411 | cleared=yes ;; 412 | esac 413 | case "$arg" in 414 | -D*|-I*) 415 | set fnord "$@" "$arg"; shift ;; 416 | # Strip any option that makedepend may not understand. Remove 417 | # the object too, otherwise makedepend will parse it as a source file. 418 | -*|$object) 419 | ;; 420 | *) 421 | set fnord "$@" "$arg"; shift ;; 422 | esac 423 | done 424 | obj_suffix="`echo $object | sed 's/^.*\././'`" 425 | touch "$tmpdepfile" 426 | ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" 427 | rm -f "$depfile" 428 | cat < "$tmpdepfile" > "$depfile" 429 | sed '1,2d' "$tmpdepfile" | tr ' ' ' 430 | ' | \ 431 | ## Some versions of the HPUX 10.20 sed can't process this invocation 432 | ## correctly. Breaking it into two sed invocations is a workaround. 433 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 434 | rm -f "$tmpdepfile" "$tmpdepfile".bak 435 | ;; 436 | 437 | cpp) 438 | # Important note: in order to support this mode, a compiler *must* 439 | # always write the preprocessed file to stdout. 440 | "$@" || exit $? 441 | 442 | # Remove the call to Libtool. 443 | if test "$libtool" = yes; then 444 | while test $1 != '--mode=compile'; do 445 | shift 446 | done 447 | shift 448 | fi 449 | 450 | # Remove `-o $object'. 451 | IFS=" " 452 | for arg 453 | do 454 | case $arg in 455 | -o) 456 | shift 457 | ;; 458 | $object) 459 | shift 460 | ;; 461 | *) 462 | set fnord "$@" "$arg" 463 | shift # fnord 464 | shift # $arg 465 | ;; 466 | esac 467 | done 468 | 469 | "$@" -E | 470 | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ 471 | -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | 472 | sed '$ s: \\$::' > "$tmpdepfile" 473 | rm -f "$depfile" 474 | echo "$object : \\" > "$depfile" 475 | cat < "$tmpdepfile" >> "$depfile" 476 | sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" 477 | rm -f "$tmpdepfile" 478 | ;; 479 | 480 | msvisualcpp) 481 | # Important note: in order to support this mode, a compiler *must* 482 | # always write the preprocessed file to stdout, regardless of -o, 483 | # because we must use -o when running libtool. 484 | "$@" || exit $? 485 | IFS=" " 486 | for arg 487 | do 488 | case "$arg" in 489 | "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") 490 | set fnord "$@" 491 | shift 492 | shift 493 | ;; 494 | *) 495 | set fnord "$@" "$arg" 496 | shift 497 | shift 498 | ;; 499 | esac 500 | done 501 | "$@" -E | 502 | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" 503 | rm -f "$depfile" 504 | echo "$object : \\" > "$depfile" 505 | . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" 506 | echo " " >> "$depfile" 507 | . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" 508 | rm -f "$tmpdepfile" 509 | ;; 510 | 511 | none) 512 | exec "$@" 513 | ;; 514 | 515 | *) 516 | echo "Unknown depmode $depmode" 1>&2 517 | exit 1 518 | ;; 519 | esac 520 | 521 | exit 0 522 | 523 | # Local Variables: 524 | # mode: shell-script 525 | # sh-indentation: 2 526 | # eval: (add-hook 'write-file-hooks 'time-stamp) 527 | # time-stamp-start: "scriptversion=" 528 | # time-stamp-format: "%:y-%02m-%02d.%02H" 529 | # time-stamp-end: "$" 530 | # End: 531 | -------------------------------------------------------------------------------- /src/elfcore.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005-2008, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Markus Gutschke, Carl Crous 32 | */ 33 | 34 | #ifndef _ELFCORE_H 35 | #define _ELFCORE_H 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /* We currently only support x86-32, x86-64, ARM, and MIPS on Linux. 41 | * Porting to other related platforms should not be difficult. 42 | */ 43 | #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \ 44 | defined(__mips__)) && defined(__linux) 45 | 46 | #include 47 | #include 48 | #include 49 | #include "config.h" 50 | 51 | 52 | /* Define the DUMPER symbol to make sure that there is exactly one 53 | * core dumper built into the library. 54 | */ 55 | #define DUMPER "ELF" 56 | 57 | /* By the time that we get a chance to read CPU registers in the 58 | * calling thread, they are already in a not particularly useful 59 | * state. Besides, there will be multiple frames on the stack that are 60 | * just making the core file confusing. To fix this problem, we take a 61 | * snapshot of the frame pointer, stack pointer, and instruction 62 | * pointer at an earlier time, and then insert these values into the 63 | * core file. 64 | */ 65 | 66 | #if defined(__i386__) || defined(__x86_64__) 67 | typedef struct i386_regs { /* Normal (non-FPU) CPU registers */ 68 | #ifdef __x86_64__ 69 | #define BP rbp 70 | #define SP rsp 71 | #define IP rip 72 | uint64_t r15,r14,r13,r12,rbp,rbx,r11,r10; 73 | uint64_t r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax; 74 | uint64_t rip,cs,eflags; 75 | uint64_t rsp,ss; 76 | uint64_t fs_base, gs_base; 77 | uint64_t ds,es,fs,gs; 78 | #else 79 | #define BP ebp 80 | #define SP esp 81 | #define IP eip 82 | uint32_t ebx, ecx, edx, esi, edi, ebp, eax; 83 | uint16_t ds, __ds, es, __es; 84 | uint16_t fs, __fs, gs, __gs; 85 | uint32_t orig_eax, eip; 86 | uint16_t cs, __cs; 87 | uint32_t eflags, esp; 88 | uint16_t ss, __ss; 89 | #endif 90 | } i386_regs; 91 | #elif defined(__ARM_ARCH_3__) 92 | typedef struct arm_regs { /* General purpose registers */ 93 | #define BP uregs[11] /* Frame pointer */ 94 | #define SP uregs[13] /* Stack pointer */ 95 | #define IP uregs[15] /* Program counter */ 96 | #define LR uregs[14] /* Link register */ 97 | long uregs[18]; 98 | } arm_regs; 99 | #elif defined(__mips__) 100 | typedef struct mips_regs { 101 | unsigned long pad[6]; /* Unused padding to match kernel structures */ 102 | unsigned long uregs[32]; /* General purpose registers. */ 103 | unsigned long hi; /* Used for multiplication and division. */ 104 | unsigned long lo; 105 | unsigned long cp0_epc; /* Program counter. */ 106 | unsigned long cp0_badvaddr; 107 | unsigned long cp0_status; 108 | unsigned long cp0_cause; 109 | unsigned long unused; 110 | } mips_regs; 111 | #endif 112 | 113 | #if defined(__i386__) && defined(__GNUC__) 114 | /* On x86 we provide an optimized version of the FRAME() macro, if the 115 | * compiler supports a GCC-style asm() directive. This results in somewhat 116 | * more accurate values for CPU registers. 117 | */ 118 | typedef struct Frame { 119 | struct i386_regs uregs; 120 | int errno_; 121 | pid_t tid; 122 | } Frame; 123 | #define FRAME(f) Frame f; \ 124 | do { \ 125 | f.errno_ = errno; \ 126 | f.tid = sys_gettid(); \ 127 | __asm__ volatile ( \ 128 | "push %%ebp\n" \ 129 | "push %%ebx\n" \ 130 | "mov %%ebx,0(%%eax)\n" \ 131 | "mov %%ecx,4(%%eax)\n" \ 132 | "mov %%edx,8(%%eax)\n" \ 133 | "mov %%esi,12(%%eax)\n" \ 134 | "mov %%edi,16(%%eax)\n" \ 135 | "mov %%ebp,20(%%eax)\n" \ 136 | "mov %%eax,24(%%eax)\n" \ 137 | "mov %%ds,%%ebx\n" \ 138 | "mov %%ebx,28(%%eax)\n" \ 139 | "mov %%es,%%ebx\n" \ 140 | "mov %%ebx,32(%%eax)\n" \ 141 | "mov %%fs,%%ebx\n" \ 142 | "mov %%ebx,36(%%eax)\n" \ 143 | "mov %%gs,%%ebx\n" \ 144 | "mov %%ebx, 40(%%eax)\n" \ 145 | "call 0f\n" \ 146 | "0:pop %%ebx\n" \ 147 | "add $1f-0b,%%ebx\n" \ 148 | "mov %%ebx,48(%%eax)\n" \ 149 | "mov %%cs,%%ebx\n" \ 150 | "mov %%ebx,52(%%eax)\n" \ 151 | "pushf\n" \ 152 | "pop %%ebx\n" \ 153 | "mov %%ebx,56(%%eax)\n" \ 154 | "mov %%esp,%%ebx\n" \ 155 | "add $8,%%ebx\n" \ 156 | "mov %%ebx,60(%%eax)\n" \ 157 | "mov %%ss,%%ebx\n" \ 158 | "mov %%ebx,64(%%eax)\n" \ 159 | "pop %%ebx\n" \ 160 | "pop %%ebp\n" \ 161 | "1:" \ 162 | : : "a" (&f) : "memory"); \ 163 | } while (0) 164 | #define SET_FRAME(f,r) \ 165 | do { \ 166 | errno = (f).errno_; \ 167 | (r) = (f).uregs; \ 168 | } while (0) 169 | #elif defined(__x86_64__) && defined(__GNUC__) 170 | /* The FRAME and SET_FRAME macros for x86_64. */ 171 | typedef struct Frame { 172 | struct i386_regs uregs; 173 | int errno_; 174 | pid_t tid; 175 | } Frame; 176 | #define FRAME(f) Frame f; \ 177 | do { \ 178 | f.errno_ = errno; \ 179 | f.tid = sys_gettid(); \ 180 | __asm__ volatile ( \ 181 | "push %%rbp\n" \ 182 | "push %%rbx\n" \ 183 | "mov %%r15,0(%%rax)\n" \ 184 | "mov %%r14,8(%%rax)\n" \ 185 | "mov %%r13,16(%%rax)\n" \ 186 | "mov %%r12,24(%%rax)\n" \ 187 | "mov %%rbp,32(%%rax)\n" \ 188 | "mov %%rbx,40(%%rax)\n" \ 189 | "mov %%r11,48(%%rax)\n" \ 190 | "mov %%r10,56(%%rax)\n" \ 191 | "mov %%r9,64(%%rax)\n" \ 192 | "mov %%r8,72(%%rax)\n" \ 193 | "mov %%rax,80(%%rax)\n" \ 194 | "mov %%rcx,88(%%rax)\n" \ 195 | "mov %%rdx,96(%%rax)\n" \ 196 | "mov %%rsi,104(%%rax)\n" \ 197 | "mov %%rdi,112(%%rax)\n" \ 198 | "mov %%ds,%%rbx\n" \ 199 | "mov %%rbx,184(%%rax)\n" \ 200 | "mov %%es,%%rbx\n" \ 201 | "mov %%rbx,192(%%rax)\n" \ 202 | "mov %%fs,%%rbx\n" \ 203 | "mov %%rbx,200(%%rax)\n" \ 204 | "mov %%gs,%%rbx\n" \ 205 | "mov %%rbx,208(%%rax)\n" \ 206 | "call 0f\n" \ 207 | "0:pop %%rbx\n" \ 208 | "add $1f-0b,%%rbx\n" \ 209 | "mov %%rbx,128(%%rax)\n" \ 210 | "mov %%cs,%%rbx\n" \ 211 | "mov %%rbx,136(%%rax)\n" \ 212 | "pushf\n" \ 213 | "pop %%rbx\n" \ 214 | "mov %%rbx,144(%%rax)\n" \ 215 | "mov %%rsp,%%rbx\n" \ 216 | "add $16,%%ebx\n" \ 217 | "mov %%rbx,152(%%rax)\n" \ 218 | "mov %%ss,%%rbx\n" \ 219 | "mov %%rbx,160(%%rax)\n" \ 220 | "pop %%rbx\n" \ 221 | "pop %%rbp\n" \ 222 | "1:" \ 223 | : : "a" (&f) : "memory"); \ 224 | } while (0) 225 | #define SET_FRAME(f,r) \ 226 | do { \ 227 | errno = (f).errno_; \ 228 | (f).uregs.fs_base = (r).fs_base; \ 229 | (f).uregs.gs_base = (r).gs_base; \ 230 | (r) = (f).uregs; \ 231 | } while (0) 232 | #elif defined(__ARM_ARCH_3__) && defined(__GNUC__) 233 | /* ARM calling conventions are a little more tricky. A little assembly 234 | * helps in obtaining an accurate snapshot of all registers. 235 | */ 236 | typedef struct Frame { 237 | struct arm_regs arm; 238 | int errno_; 239 | pid_t tid; 240 | } Frame; 241 | #define FRAME(f) Frame f; \ 242 | do { \ 243 | long cpsr; \ 244 | f.errno_ = errno; \ 245 | f.tid = sys_gettid(); \ 246 | __asm__ volatile( \ 247 | "stmia %0, {r0-r15}\n" /* All integer regs */\ 248 | : : "r"(&f.arm) : "memory"); \ 249 | f.arm.uregs[16] = 0; \ 250 | __asm__ volatile( \ 251 | "mrs %0, cpsr\n" /* Condition code reg */\ 252 | : "=r"(cpsr)); \ 253 | f.arm.uregs[17] = cpsr; \ 254 | } while (0) 255 | #define SET_FRAME(f,r) \ 256 | do { \ 257 | /* Don't override the FPU status register. */\ 258 | /* Use the value obtained from ptrace(). This*/\ 259 | /* works, because our code does not perform */\ 260 | /* any FPU operations, itself. */\ 261 | long fps = (f).arm.uregs[16]; \ 262 | errno = (f).errno_; \ 263 | (r) = (f).arm; \ 264 | (r).uregs[16] = fps; \ 265 | } while (0) 266 | #elif defined(__mips__) && defined(__GNUC__) 267 | typedef struct Frame { 268 | struct mips_regs mips_regs; 269 | int errno_; 270 | pid_t tid; 271 | } Frame; 272 | #define MIPSREG(n) ({ register unsigned long r __asm__("$"#n); r; }) 273 | #define FRAME(f) Frame f = { 0 }; \ 274 | do { \ 275 | unsigned long hi, lo; \ 276 | register unsigned long pc __asm__("$31"); \ 277 | f.mips_regs.uregs[ 0] = MIPSREG( 0); \ 278 | f.mips_regs.uregs[ 1] = MIPSREG( 1); \ 279 | f.mips_regs.uregs[ 2] = MIPSREG( 2); \ 280 | f.mips_regs.uregs[ 3] = MIPSREG( 3); \ 281 | f.mips_regs.uregs[ 4] = MIPSREG( 4); \ 282 | f.mips_regs.uregs[ 5] = MIPSREG( 5); \ 283 | f.mips_regs.uregs[ 6] = MIPSREG( 6); \ 284 | f.mips_regs.uregs[ 7] = MIPSREG( 7); \ 285 | f.mips_regs.uregs[ 8] = MIPSREG( 8); \ 286 | f.mips_regs.uregs[ 9] = MIPSREG( 9); \ 287 | f.mips_regs.uregs[10] = MIPSREG(10); \ 288 | f.mips_regs.uregs[11] = MIPSREG(11); \ 289 | f.mips_regs.uregs[12] = MIPSREG(12); \ 290 | f.mips_regs.uregs[13] = MIPSREG(13); \ 291 | f.mips_regs.uregs[14] = MIPSREG(14); \ 292 | f.mips_regs.uregs[15] = MIPSREG(15); \ 293 | f.mips_regs.uregs[16] = MIPSREG(16); \ 294 | f.mips_regs.uregs[17] = MIPSREG(17); \ 295 | f.mips_regs.uregs[18] = MIPSREG(18); \ 296 | f.mips_regs.uregs[19] = MIPSREG(19); \ 297 | f.mips_regs.uregs[20] = MIPSREG(20); \ 298 | f.mips_regs.uregs[21] = MIPSREG(21); \ 299 | f.mips_regs.uregs[22] = MIPSREG(22); \ 300 | f.mips_regs.uregs[23] = MIPSREG(23); \ 301 | f.mips_regs.uregs[24] = MIPSREG(24); \ 302 | f.mips_regs.uregs[25] = MIPSREG(25); \ 303 | f.mips_regs.uregs[26] = MIPSREG(26); \ 304 | f.mips_regs.uregs[27] = MIPSREG(27); \ 305 | f.mips_regs.uregs[28] = MIPSREG(28); \ 306 | f.mips_regs.uregs[29] = MIPSREG(29); \ 307 | f.mips_regs.uregs[30] = MIPSREG(30); \ 308 | f.mips_regs.uregs[31] = MIPSREG(31); \ 309 | __asm__ volatile ("mfhi %0" : "=r"(hi)); \ 310 | __asm__ volatile ("mflo %0" : "=r"(lo)); \ 311 | __asm__ volatile ("jal 1f; 1:nop" : "=r"(pc)); \ 312 | f.mips_regs.hi = hi; \ 313 | f.mips_regs.lo = lo; \ 314 | f.mips_regs.cp0_epc = pc; \ 315 | f.errno_ = errno; \ 316 | f.tid = sys_gettid(); \ 317 | } while (0) 318 | #define SET_FRAME(f,r) \ 319 | do { \ 320 | errno = (f).errno_; \ 321 | memcpy((r).uregs, (f).mips_regs.uregs, \ 322 | 32*sizeof(unsigned long)); \ 323 | (r).hi = (f).mips_regs.hi; \ 324 | (r).lo = (f).mips_regs.lo; \ 325 | (r).cp0_epc = (f).mips_regs.cp0_epc; \ 326 | } while (0) 327 | #else 328 | /* If we do not have a hand-optimized assembly version of the FRAME() 329 | * macro, we cannot reliably unroll the stack. So, we show a few additional 330 | * stack frames for the coredumper. 331 | */ 332 | typedef struct Frame { 333 | pid_t tid; 334 | } Frame; 335 | #define FRAME(f) Frame f; do { f.tid = sys_gettid(); } while (0) 336 | #define SET_FRAME(f,r) do { } while (0) 337 | #endif 338 | 339 | 340 | /* Internal function for generating a core file. This API can change without 341 | * notice and is only supposed to be used internally by the core dumper. 342 | * 343 | * This function works for both single- and multi-threaded core 344 | * dumps. If called as 345 | * 346 | * FRAME(frame); 347 | * InternalGetCoreDump(&frame, 0, NULL, ap); 348 | * 349 | * it creates a core file that only contains information about the 350 | * calling thread. 351 | * 352 | * Optionally, the caller can provide information about other threads 353 | * by passing their process ids in "thread_pids". The process id of 354 | * the caller should not be included in this array. All of the threads 355 | * must have been attached to with ptrace(), prior to calling this 356 | * function. They will be detached when "InternalGetCoreDump()" returns. 357 | * 358 | * This function either returns a file handle that can be read for obtaining 359 | * a core dump, or "-1" in case of an error. In the latter case, "errno" 360 | * will be set appropriately. 361 | * 362 | * While "InternalGetCoreDump()" is not technically async signal safe, you 363 | * might be tempted to invoke it from a signal handler. The code goes to 364 | * great lengths to make a best effort that this will actually work. But in 365 | * any case, you must make sure that you preserve the value of "errno" 366 | * yourself. It is guaranteed to be clobbered otherwise. 367 | * 368 | * Also, "InternalGetCoreDump" is not strictly speaking re-entrant. Again, 369 | * it makes a best effort to behave reasonably when called in a multi- 370 | * threaded environment, but it is ultimately the caller's responsibility 371 | * to provide locking. 372 | */ 373 | int InternalGetCoreDump(void *frame, int num_threads, pid_t *thread_pids, 374 | va_list ap 375 | /* const struct CoreDumpParameters *params, 376 | const char *file_name, 377 | const char *PATH 378 | */); 379 | 380 | #endif 381 | 382 | #ifdef __cplusplus 383 | } 384 | #endif 385 | #endif /* _ELFCORE_H */ 386 | -------------------------------------------------------------------------------- /examples/tftpd.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2005, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Markus Gutschke 32 | * 33 | * This file demonstrates how to add a core dump interface to an existing 34 | * service. Typically, you would want to add the call to GetCoreDump() 35 | * to an existing interface exposed by your server. But if no such interface 36 | * exists, you could also adapt the TFTP code in this module to run as a 37 | * thread in your server. 38 | * 39 | * The code in this module does not perform any type of access control. 40 | * As corefiles can expose security sensitive data (e.g. passwords), you 41 | * would need to add appropriate access controls when using this (or similar) 42 | * code in a production environment. 43 | */ 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | 62 | 63 | #undef NO_THREADS /* Support only one connection at a time. */ 64 | #undef CAN_READ_FILES /* Supports reading files from "/tftpboot/..." */ 65 | #undef CAN_WRITE_FILES /* Supports updating files in "/tftpboot/..." */ 66 | #define CAN_READ_CORES /* Supports serving "core" snapshot files. */ 67 | 68 | 69 | #ifndef TFTPHDRSIZE 70 | #define TFTPHDRSIZE 4 71 | #endif 72 | 73 | 74 | /* The "Request" structure contains all the parameters that get passed 75 | * from the main server loop to the thread that is processing a given 76 | * TFTP connection. 77 | */ 78 | typedef struct Request { 79 | int debug; 80 | int id; 81 | int fd; 82 | struct tftphdr *tftp; 83 | char buf[TFTPHDRSIZE + SEGSIZE]; 84 | size_t count; 85 | struct sockaddr_in addr; 86 | socklen_t len; 87 | const char *core_name; 88 | char **dirs; 89 | int no_ack; 90 | int sanitize; 91 | } Request; 92 | 93 | #define DBG(...) do { \ 94 | if (debug) \ 95 | fprintf(stderr, __VA_ARGS__); \ 96 | } while (0) 97 | 98 | /* tftp_thread() runs in its own thread (unless NO_THREADS is defined). This 99 | * function processes a single TFTP connection. 100 | */ 101 | static void *tftp_thread(void *arg) { 102 | #define debug (request->debug) 103 | Request *request = (Request *)arg; 104 | struct tftphdr *tftp = request->tftp; 105 | int fd = -1; 106 | int src = -1; 107 | int err = EBADOP; 108 | int ioerr = 0; 109 | struct sockaddr_in addr; 110 | socklen_t len; 111 | char *raw_file_name, *mode, *msg, msg_buf[80]; 112 | char *file_name = NULL; 113 | 114 | /* Create a new socket for this connection. */ 115 | if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 116 | perror("socket"); 117 | exit(1); 118 | } 119 | 120 | /* Connect this socket to the outgoing interface. */ 121 | len = sizeof(addr); 122 | if (getsockname(request->fd, (struct sockaddr *)&addr, &len) >= 0 && 123 | len >= sizeof(struct sockaddr_in)) { 124 | DBG("Responding to %s:%d\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port)); 125 | addr.sin_port = 0; 126 | bind(fd, (struct sockaddr *)&addr, len); 127 | } 128 | 129 | /* Get file name and transfer mode from the incoming TFTP packet. */ 130 | if (!(raw_file_name = request->buf + 2, mode = memchr(raw_file_name, '\000', 131 | request->count - 1 - (raw_file_name - request->buf))) || 132 | !(++mode, memchr(mode, '\000', request->count - (mode - request->buf)))){ 133 | char *ptr; 134 | msg = "Truncated request"; 135 | 136 | error: 137 | /* Send error message back to client. */ 138 | DBG("%s\n", msg); 139 | ptr = strrchr(strcpy(tftp->th_msg, msg), '\000') + 1; 140 | tftp->th_opcode = htons(ERROR); 141 | tftp->th_code = htons(err); 142 | sendto(fd, tftp, ptr-request->buf, 0, 143 | (struct sockaddr *)&request->addr, request->len); 144 | goto done; 145 | } 146 | 147 | /* Only text and binary transfer modes are supported. */ 148 | if (strcasecmp(mode, "netascii") && strcasecmp(mode, "octet")) { 149 | msg = "Unsupported transfer mode"; 150 | goto error; 151 | } 152 | 153 | /* Check whether client requested a "core" snapshot of the running process.*/ 154 | if (!strcmp(raw_file_name, request->core_name)) { 155 | #ifdef CAN_READ_CORES 156 | /* Core files must be transferred in binary. */ 157 | if (strcasecmp(mode, "octet")) { 158 | err = EBADOP; 159 | msg = "Core files must be transferred in binary"; 160 | goto error; 161 | } 162 | 163 | /* Writing core files is not a supported operation. */ 164 | if (ntohs(tftp->th_opcode) == WRQ) { 165 | err = EBADOP; 166 | msg = "Core files cannot be written"; 167 | goto error; 168 | } 169 | 170 | /* Here we go. Create a snapshot of this process. */ 171 | src = GetCoreDump(); 172 | 173 | /* If we failed to created a core file, report error to the client. */ 174 | if (src < 0) { 175 | err = ENOTFOUND; 176 | *msg_buf = '\000'; 177 | msg = strerror_r(errno, msg_buf, sizeof(msg_buf)); 178 | goto error; 179 | } 180 | #else 181 | err = ENOTFOUND; 182 | msg = "Core file support is not enabled"; 183 | goto error; 184 | #endif 185 | } else { 186 | #if defined(CAN_READ_FILES) || defined(CAN_WRITE_FILES) 187 | /* TFTP is a very simple protocol, which does not support any user 188 | * authentication/authorization. So, we have to be very conservative 189 | * when accessing files. Unless overridden on the command line, this 190 | * server will only access files underneath the "/tftpboot" directory. 191 | * It only serves world-readable files, and it only allow writing to 192 | * world-writable files. 193 | */ 194 | static char *tftpdirs[] = { "/tftpboot", NULL }; 195 | char **dirs = tftpdirs; 196 | struct stat sb; 197 | 198 | /* Unless the user requested otherwise, restrict to "/tftpboot/..." */ 199 | if (*request->dirs) { 200 | dirs = request->dirs; 201 | } 202 | 203 | /* If "sanitize" option is set, prepend "/tftpboot" (or name of the first 204 | * source directory listed on the command line) to any absolute file 205 | * names. 206 | */ 207 | if (*raw_file_name == '/' && request->sanitize) { 208 | char *path = dirs[0]; 209 | strcat(strcat(strcpy(malloc(strlen(path) + strlen(raw_file_name) + 2), 210 | path), "/"), raw_file_name); 211 | 212 | } else { 213 | file_name = strdup(raw_file_name); 214 | } 215 | 216 | /* Check file attributes. */ 217 | memset(&sb, 0, sizeof(sb)); 218 | if (*file_name == '/') { 219 | int ok = 0; 220 | char **ptr; 221 | 222 | /* Search for file in all source directories (normally just 223 | * "/tftpboot") 224 | */ 225 | for (ptr = &dirs[0]; *ptr; ptr++) { 226 | if (!strncmp(*ptr, file_name, strlen(*ptr)) && 227 | stat(file_name, &sb) >= 0 && S_ISREG(sb.st_mode)) { 228 | ok++; 229 | break; 230 | } 231 | } 232 | if (!ok) { 233 | file_not_found: 234 | /* Only pre-existing files can be accessed. */ 235 | if (request->no_ack) 236 | goto done; 237 | else { 238 | err = ENOTFOUND; 239 | msg = "File not found"; 240 | goto error; 241 | } 242 | } 243 | } else { 244 | char **ptr, *absolute_file_name = NULL; 245 | 246 | /* Search for file in all source directories (normally just 247 | * "/tftpboot") 248 | */ 249 | for (ptr = &dirs[0]; *ptr; ptr++) { 250 | absolute_file_name = strcat(strcat(strcpy(malloc(strlen(*ptr) + 251 | strlen(file_name) + 2), 252 | *ptr), "/"), file_name); 253 | if (stat(absolute_file_name, &sb) >= 0 && S_ISREG(sb.st_mode)) 254 | break; 255 | free(absolute_file_name); 256 | absolute_file_name = NULL; 257 | } 258 | if (!absolute_file_name) 259 | goto file_not_found; 260 | free(file_name); 261 | file_name = absolute_file_name; 262 | } 263 | 264 | /* Check whether the necessary support for reading/writing is compiled 265 | * into this server, and whether the file is world-readable/writable. 266 | */ 267 | if (ntohs(tftp->th_opcode) == WRQ) { 268 | #ifdef CAN_WRITE_FILES 269 | if (!(sb.st_mode & S_IWOTH) || 270 | (src = open(file_name, O_WRONLY)) < 0) 271 | #endif 272 | { 273 | access_denied: 274 | err = EACCESS; 275 | msg = "Access denied"; 276 | goto error; 277 | } 278 | } else { 279 | #ifdef CAN_READ_FILES 280 | if (!(sb.st_mode & S_IROTH) || 281 | (src = open(file_name, O_RDONLY)) < 0) 282 | #endif 283 | goto access_denied; 284 | } 285 | #else 286 | err = ENOTFOUND; 287 | msg = "File operations are not enabled"; 288 | goto error; 289 | #endif 290 | } 291 | 292 | if (ntohs(tftp->th_opcode) == RRQ) { 293 | DBG("received RRQ <%s, %s>\n", raw_file_name, mode); 294 | #if defined(CAN_READ_FILES) || defined(CAN_READ_CORES) 295 | unsigned short block = 0; 296 | int count; 297 | 298 | /* Mainloop for serving files to clients. */ 299 | do { 300 | char buf[TFTPHDRSIZE + SEGSIZE]; 301 | struct tftphdr *send_tftp = (struct tftphdr *)buf; 302 | char *ptr = send_tftp->th_msg; 303 | int retry; 304 | 305 | /* Deal with partial reads, and reblock in units of 512 bytes. */ 306 | count = 0; 307 | while (!ioerr && count < SEGSIZE) { 308 | int rc = read(src, ptr + count, SEGSIZE - count); 309 | if (rc < 0) { 310 | if (errno == EINTR) 311 | continue; 312 | ioerr = errno; 313 | break; 314 | } else if (rc == 0) { 315 | break; 316 | } 317 | count += rc; 318 | } 319 | 320 | /* Report any read errors back to the client. */ 321 | if (count == 0 && ioerr) { 322 | err = ENOTFOUND; 323 | *msg_buf = '\000'; 324 | msg = strerror_r(ioerr, msg_buf, sizeof(msg_buf)); 325 | goto error; 326 | } 327 | send_tftp->th_opcode = htons(DATA); 328 | send_tftp->th_block = htons(++block); 329 | 330 | /* Transmit a single packet. Retry if necessary. */ 331 | retry = 10; 332 | for (;;) { 333 | int rc; 334 | 335 | /* Terminate entire transfers after too many retries. */ 336 | if (--retry < 0) 337 | goto done; 338 | 339 | /* Send one 512 byte packet. */ 340 | DBG("send DATA \n", block); 341 | if (sendto(fd, send_tftp, TFTPHDRSIZE + count, 0, 342 | (struct sockaddr *)&request->addr, request->len) < 0) { 343 | if (errno == EINTR) 344 | continue; 345 | goto done; 346 | } 347 | 348 | /* Wait for response from client. */ 349 | do { 350 | fd_set in_fds; 351 | struct timeval timeout; 352 | FD_ZERO(&in_fds); 353 | FD_SET(fd, &in_fds); 354 | timeout.tv_sec = 5; 355 | timeout.tv_usec = 0; 356 | rc = select(fd+1, &in_fds, NULL, NULL, &timeout); 357 | } while (rc < 0 && errno == EINTR); 358 | 359 | /* If no response received, try sending payload again. */ 360 | if (rc == 0) 361 | continue; 362 | 363 | /* Receive actual response. */ 364 | rc = recv(fd, tftp, TFTPHDRSIZE + SEGSIZE, MSG_TRUNC); 365 | 366 | /* If operation failed, terminate entire transfer. */ 367 | if (rc < 0) { 368 | if (errno == EINTR) 369 | continue; 370 | goto done; 371 | } 372 | 373 | /* Done transmitting this block, after receiving matching ACK */ 374 | if (rc >= TFTPHDRSIZE) { 375 | switch (ntohs(tftp->th_opcode)) { 376 | case ACK: 377 | DBG("received ACK \n", ntohs(tftp->th_block)); 378 | break; 379 | case RRQ: 380 | DBG("received RRQ\n"); 381 | break; 382 | case WRQ: 383 | DBG("received WRQ\n"); 384 | break; 385 | case DATA: 386 | DBG("received DATA\n"); 387 | break; 388 | case ERROR: 389 | DBG("received ERROR\n"); 390 | break; 391 | default: 392 | DBG("unexpected data, op=%d\n", ntohs(tftp->th_opcode)); 393 | break; 394 | } 395 | } 396 | if (rc >= TFTPHDRSIZE && 397 | ntohs(tftp->th_opcode) == ACK && 398 | tftp->th_block == send_tftp->th_block) 399 | break; 400 | } 401 | } while (count); 402 | #endif 403 | } else { 404 | #ifdef CAN_WRITE_FILES 405 | /* TODO: Add support for writing files */ 406 | #endif 407 | } 408 | 409 | done: 410 | /* Clean up, close all file handles, and release memory */ 411 | if (fd >= 0) 412 | close(fd); 413 | if (src >= 0) 414 | close(src); 415 | if (file_name) 416 | free(file_name); 417 | free(request); 418 | return 0; 419 | #undef debug 420 | } 421 | 422 | 423 | /* This is a very basic TFTP server implementing RFC 1350, but none of the 424 | * optional protocol extensions (e.g. no block size negotiation, and no 425 | * multicasting). 426 | */ 427 | int main(int argc, char *argv[]) { 428 | static const struct option long_opts[] = { 429 | /* Set file name for "core" snapshot file of running process. */ 430 | { "core", 1, NULL, 'c' }, 431 | 432 | /* Enable debugging output. */ 433 | { "debug", 0, NULL, 'd' }, 434 | 435 | /* Print usage information for this server. */ 436 | { "help", 0, NULL, 'h' }, 437 | 438 | /* Suppress negative acknowledge for non-existant files. */ 439 | { "noack", 0, NULL, 'n' }, 440 | 441 | /* Set port number to listen on. */ 442 | { "port", 1, NULL, 'p' }, 443 | 444 | /* Sanitize requests for absolute filenames by prepending the name of the 445 | * first directory specified on the command line. If no directory is 446 | * given, prepend "/tftpboot/". 447 | */ 448 | { "sanitize", 0, NULL, 's' }, 449 | { NULL, 0, NULL, 0 } }; 450 | static const char *opt_string = "c:dhnp:s"; 451 | const char *core_name = "core"; 452 | int debug = 0; 453 | int no_ack = 0; 454 | int port = -1; 455 | int sanitize = 0; 456 | char **dirs = NULL; 457 | int server_fd = 0; 458 | int id = 0; 459 | 460 | /* Parse command line options. */ 461 | for (;;) { 462 | int idx = 0; 463 | int c = getopt_long(argc, argv, opt_string, long_opts, &idx); 464 | if (c == -1) 465 | break; 466 | switch (c) { 467 | case 'c': 468 | core_name = optarg; 469 | break; 470 | case 'd': 471 | debug = 1; 472 | break; 473 | case 'n': 474 | no_ack = 1; 475 | break; 476 | case 'p': 477 | port = atoi(optarg); 478 | if (port <= 0 || port > 65535) { 479 | fprintf(stderr, "Port out of range: %d\n", port); 480 | exit(1); 481 | } 482 | break; 483 | case 's': 484 | sanitize = 1; 485 | break; 486 | case 'h': 487 | default: 488 | fprintf(stderr, 489 | "Usage: %s --core --debug --help --port --noack " 490 | "--sanitize\n", 491 | argv[0]); 492 | exit(c != 'h'); 493 | } 494 | } 495 | 496 | /* All remaining command line arguments (if any) list the directories of 497 | * files that this server can access. If no directories are given, then 498 | * only files in "/tftpboot/..." are accessible. 499 | */ 500 | dirs = argv + optind; 501 | 502 | /* If a port is given on the command line, then listen on. Otherwise, 503 | * assume that stdin is already connected to a server port. This allows 504 | * us to run the server from inetd. 505 | */ 506 | if (port >= 0) { 507 | struct sockaddr_in addr; 508 | 509 | server_fd = socket(PF_INET, SOCK_DGRAM, 0); 510 | if (server_fd < 0) { 511 | perror("socket"); 512 | exit(1); 513 | } 514 | memset(&addr, 0, sizeof(addr)); 515 | addr.sin_family = AF_INET; 516 | addr.sin_port = htons(port); 517 | addr.sin_addr.s_addr = INADDR_ANY; 518 | if (bind(server_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) <0){ 519 | perror("bind"); 520 | exit(1); 521 | } 522 | } 523 | 524 | /* Server mainloop. Accept incoming connections and spawn threads to 525 | * serve the requests. 526 | */ 527 | for (;;) { 528 | const char *msg; 529 | char buf[TFTPHDRSIZE + SEGSIZE]; 530 | struct tftphdr *tftp = (struct tftphdr *)buf; 531 | struct sockaddr_in addr; 532 | socklen_t len; 533 | int count, type; 534 | Request *request; 535 | #ifndef NO_THREADS 536 | pthread_t thread; 537 | #endif 538 | 539 | /* Receive next request. */ 540 | len = sizeof(addr); 541 | count = recvfrom(server_fd, tftp, sizeof(buf), MSG_TRUNC, 542 | (struct sockaddr *)&addr, &len); 543 | if (count < 0) { 544 | if (errno == EINTR) 545 | continue; 546 | perror("recvfrom"); 547 | exit(1); 548 | } 549 | 550 | /* If request arrived from unsupported address, just ignore it. */ 551 | if (len < sizeof(struct sockaddr_in)) 552 | continue; 553 | 554 | /* If request was truncated, report error back to client. */ 555 | if (count < sizeof(tftp)) { 556 | char *ptr; 557 | msg = "Truncated request"; 558 | send_error: 559 | /* Send error message to client. */ 560 | DBG("%s\n", msg); 561 | ptr = strrchr(strcpy(tftp->th_msg, msg), '\000') + 1; 562 | tftp->th_opcode = htons(ERROR); 563 | tftp->th_code = htons(EBADOP); 564 | sendto(server_fd, tftp, ptr-buf, 0, (struct sockaddr *)&addr, len); 565 | continue; 566 | } 567 | 568 | /* Determine whether this was a read or write request. */ 569 | type = ntohs(tftp->th_opcode); 570 | if (type != RRQ && type != WRQ) { 571 | msg = "Request must be RRQ or WRQ"; 572 | goto send_error; 573 | } 574 | 575 | /* Build "Request" data structure with parameters describing connection. */ 576 | request = calloc(sizeof(Request), 1); 577 | request->debug = debug; 578 | request->id = id++; 579 | request->fd = server_fd; 580 | request->tftp = (struct tftphdr *)&request->buf; 581 | request->count = count; 582 | request->len = len; 583 | request->core_name = core_name; 584 | request->dirs = dirs; 585 | request->no_ack = no_ack; 586 | request->sanitize = sanitize; 587 | memcpy(&request->buf, buf, count); 588 | memcpy(&request->addr, &addr, len); 589 | 590 | /* Hand request off to its own thread. */ 591 | #ifdef NO_THREADS 592 | tftp_thread(request); 593 | #else 594 | pthread_create(&thread, NULL, tftp_thread, request); 595 | #endif 596 | } 597 | } 598 | --------------------------------------------------------------------------------