crunch, from James da Silva at UMD
This commit is contained in:
parent
6dc403d977
commit
ee36043f2b
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 1994 University of Maryland
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of U.M. not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. U.M. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: James da Silva, Systems Design and Analysis Group
|
||||
* Computer Science Department
|
||||
* University of Maryland at College Park
|
||||
*/
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
SUBDIR=crunchgen crunchide
|
||||
|
||||
.include <bsd.subdir.mk>
|
|
@ -0,0 +1,2 @@
|
|||
# modify to taste
|
||||
BINDIR?= /usr/local/bin
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
CRUNCH 0.3 README 7/23/94
|
||||
|
||||
Crunch is available via anonymous ftp to ftp.cs.umd.edu in
|
||||
pub/bsd/crunch-0.3.tar.gz
|
||||
|
||||
WHAT'S NEW IN 0.3
|
||||
|
||||
* The prototype awk script has been replaced by a more capable and
|
||||
hopefully more robust C program.
|
||||
* No fragile template makefiles or dependencies on the details of the
|
||||
bsd build environment.
|
||||
* You can build crunched binaries even with no sources on-line, you
|
||||
just need the .o files. Crunchgen still will try to figure out as
|
||||
much as possible on its own, but you can override its guessing by
|
||||
specifying the list of .o files explicitly.
|
||||
* Crunch itself has been bmake'd and some man pages written, so it
|
||||
should be ready to install.
|
||||
* Added patch for FreeBSD from Jordan Hubbard, plus the .conf files used
|
||||
for the FreeBSD install floppies as examples.
|
||||
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
Crunch is a little package that helps create "crunched" binaries for use
|
||||
on boot, install, and fixit floppies. A crunched binary in this case is
|
||||
one where many programs have been linked together into one a.out file.
|
||||
The different programs are run depending on the value of argv[0], so
|
||||
hard links to the crunched binary suffice to simulate a perfectly normal
|
||||
system.
|
||||
|
||||
As an example, I have created an 980K crunched "fixit" binary containing
|
||||
the following programs in their entirety:
|
||||
|
||||
cat chmod cp date dd df echo ed expr hostname kill ln ls mkdir
|
||||
mt mv pwd rcp rm rmdir sh sleep stty sync test [ badsect chown
|
||||
clri disklabel dump rdump dmesg fdisk fsck halt ifconfig init
|
||||
mknod mount newfs ping reboot restore rrestore swapon umount
|
||||
ftp rsh sed telnet rlogin vi cpio gzip gunzip gzcat
|
||||
|
||||
Note carefully: vi, cpio, gzip, ed, sed, dump/restore, some networking
|
||||
utilities, and the disk management utilities, all in a binary small
|
||||
enough to fit on a 1.2 MB root filesystem floppy (albeit with the kernel
|
||||
on its own boot floppy). A more reasonable subset can be made to fit
|
||||
easily with a kernel for a decent one-disk fixit filesystem.
|
||||
|
||||
The linking together of different programs by hand is an old
|
||||
space-saving technique. Crunch automates the process by building the
|
||||
necessary stub files and makefile for you (via the crunchgen program),
|
||||
and by doctoring the symbol tables of the component .o files to allow
|
||||
them to link without "symbol multiply defined" conflicts (via the
|
||||
crunchide program).
|
||||
|
||||
|
||||
BUILDING CRUNCH
|
||||
|
||||
Just type make, then make install.
|
||||
|
||||
Crunch was written and tested under NetBSD/i386, but should work under
|
||||
other PC BSD systems that use GNU ld.
|
||||
|
||||
The crunchgen(1) and crunchide(1) man pages have more details on using
|
||||
crunch, and the examples subdirectory contains some working .conf files
|
||||
and a sample Makefile.
|
||||
|
||||
CREDITS
|
||||
|
||||
Thanks to the NetBSD team for a consistently high quality effort in
|
||||
bringing together a solid, state of the art development environment.
|
||||
|
||||
Thanks to the FreeBSD guys; Rod Grimes, Nate Williams and Jordan
|
||||
Hubbard; and to Bruce Evans, for immediate and detailed feedback on
|
||||
crunch 0.1, and for pressing me to make the prototype more useable.
|
||||
|
||||
Crunch was written for the Maruti Hard Real-Time Operating System
|
||||
project at the University of Maryland, to help make for better install
|
||||
and recovery procedures for our NetBSD-based development environment. It
|
||||
is copyright (c) 1994 by the University of Maryland under a UCB-style
|
||||
freely- redistributable notice. See the file COPYRIGHT for details.
|
||||
|
||||
Please let me know of any problems or of enhancements you make to this
|
||||
package. I'm particularly interested in the details of what you found
|
||||
was good to put on your fixit or install disks. Thanks!
|
||||
|
||||
Share and Enjoy,
|
||||
Jaime
|
||||
............................................................................
|
||||
: Stand on my shoulders, : jds@cs.umd.edu : James da Silva
|
||||
: not on my toes. : uunet!mimsy!jds : http://www.cs.umd.edu/users/jds
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
PROG=crunchgen
|
||||
SRCS=crunchgen.c crunched_skel.c
|
||||
CFLAGS+=-g -Wall
|
||||
CLEANFILES+= crunched_skel.c
|
||||
|
||||
crunched_skel.c: crunched_main.c
|
||||
${.CURDIR}/mkskel.sh ${.CURDIR}/crunched_main.c >crunched_skel.c
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 1994 University of Maryland
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of U.M. not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. U.M. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: James da Silva, Systems Design and Analysis Group
|
||||
* Computer Science Department
|
||||
* University of Maryland at College Park
|
||||
*/
|
||||
/*
|
||||
* crunched_main.c - main program for crunched binaries, it branches to a
|
||||
* particular subprogram based on the value of argv[0]. Also included
|
||||
* is a little program invoked when the crunched binary is called via
|
||||
* its EXECNAME. This one prints out the list of compiled-in binaries,
|
||||
* or calls one of them based on argv[1]. This allows the testing of
|
||||
* the crunched binary without creating all the links.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
struct stub {
|
||||
char *name;
|
||||
int (*f)();
|
||||
};
|
||||
|
||||
extern struct stub entry_points[];
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *slash, *basename;
|
||||
struct stub *ep;
|
||||
|
||||
if(argv[0] == NULL || *argv[0] == '\0')
|
||||
crunched_usage();
|
||||
|
||||
slash = strrchr(argv[0], '/');
|
||||
basename = slash? slash+1 : argv[0];
|
||||
|
||||
for(ep=entry_points; ep->name != NULL; ep++)
|
||||
if(!strcmp(basename, ep->name)) break;
|
||||
|
||||
if(ep->name)
|
||||
return ep->f(argc, argv);
|
||||
else {
|
||||
fprintf(stderr, "%s: %s not compiled in\n", EXECNAME, basename);
|
||||
crunched_usage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int crunched_main(int argc, char **argv)
|
||||
{
|
||||
struct stub *ep;
|
||||
int columns, len;
|
||||
|
||||
if(argc <= 1)
|
||||
crunched_usage();
|
||||
|
||||
return main(--argc, ++argv);
|
||||
}
|
||||
|
||||
|
||||
int crunched_usage()
|
||||
{
|
||||
int columns, len;
|
||||
struct stub *ep;
|
||||
|
||||
fprintf(stderr, "Usage: %s <prog> <args> ..., where <prog> is one of:\n",
|
||||
EXECNAME);
|
||||
columns = 0;
|
||||
for(ep=entry_points; ep->name != NULL; ep++) {
|
||||
len = strlen(ep->name) + 1;
|
||||
if(columns+len < 80)
|
||||
columns += len;
|
||||
else {
|
||||
fprintf(stderr, "\n");
|
||||
columns = len;
|
||||
}
|
||||
fprintf(stderr, " %s", ep->name);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* end of crunched_main.c */
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
.\"
|
||||
.\" Copyright (c) 1994 University of Maryland
|
||||
.\" All Rights Reserved.
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, distribute, and sell this software and its
|
||||
.\" documentation for any purpose is hereby granted without fee, provided that
|
||||
.\" the above copyright notice appear in all copies and that both that
|
||||
.\" copyright notice and this permission notice appear in supporting
|
||||
.\" documentation, and that the name of U.M. not be used in advertising or
|
||||
.\" publicity pertaining to distribution of the software without specific,
|
||||
.\" written prior permission. U.M. makes no representations about the
|
||||
.\" suitability of this software for any purpose. It is provided "as is"
|
||||
.\" without express or implied warranty.
|
||||
.\"
|
||||
.\" U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
.\" BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
.\" IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.\" Author: James da Silva, Systems Design and Analysis Group
|
||||
.\" Computer Science Department
|
||||
.\" University of Maryland at College Park
|
||||
.\"
|
||||
.Dd June 14, 1994
|
||||
.Dt CRUNCHGEN 1
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm \&crunchgen
|
||||
.Nd generates build environment for a crunched binary
|
||||
.Sh SYNOPSIS
|
||||
.Nm \&crunchgen
|
||||
.Op Fl fq
|
||||
.Op Fl m Ar makefile-name
|
||||
.Op Fl c Ar c-file-name
|
||||
.Op Fl e Ar exec-file-name
|
||||
.Op Ar conf-file
|
||||
.Sh DESCRIPTION
|
||||
|
||||
A crunched binary is a program made up of many other programs linked
|
||||
together into a single executable. The crunched binary main()
|
||||
function determines which component program to run by the contents of
|
||||
argv[0]. The main reason to crunch programs together is for fitting
|
||||
as many programs as possible onto an installation or system recovery
|
||||
floppy.
|
||||
|
||||
.Pp
|
||||
.Nm Crunchgen
|
||||
reads in the specifications in
|
||||
.Ar conf-file
|
||||
for a crunched binary, and generates a Makefile and accompanying
|
||||
top-level C source file that when built create the crunched executable
|
||||
file from the component programs. For each component program,
|
||||
.Nm crunchgen
|
||||
can optionally attempt to determine the object (.o) files that make up
|
||||
the program from its source directory Makefile. This information is
|
||||
cached between runs.
|
||||
.Nm Crunchgen
|
||||
uses the companion program
|
||||
.Nm crunchide
|
||||
to eliminate link-time conflicts between the component programs by
|
||||
hiding all unnecessary symbols.
|
||||
|
||||
.Pp
|
||||
After
|
||||
.Nm crunchgen
|
||||
is run, the crunched binary can be built by running ``make -f
|
||||
<conf-name>.mk''. The component programs' object files must already
|
||||
be built. A ``objs'' target, included in the output makefile, will
|
||||
run make in each component program's source dir to build the object
|
||||
files for the user. This is not done automatically since in release
|
||||
engineering circumstances it is generally not desireable to be
|
||||
modifying objects in other directories.
|
||||
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl c Ar c-file-name
|
||||
Set output C file name to
|
||||
.Ar c-file-name .
|
||||
The default name is ``<conf-name>.c''.
|
||||
.It Fl e Ar exec-file-name
|
||||
Set crunched binary executable file name to
|
||||
.Ar exec-file-name .
|
||||
The default name is ``<conf-name>''.
|
||||
.It Fl f
|
||||
Flush cache. Forces the recalculation of cached parameters.
|
||||
.It Fl m Ar makefile-name
|
||||
Set output Makefile name to
|
||||
.Ar makefile-name .
|
||||
The default name is ``<conf-name>.mk''.
|
||||
.It Fl q
|
||||
Quiet operation. Status messages are suppressed.
|
||||
.El
|
||||
.Sh CRUNCHGEN CONFIGURATION FILE COMMANDS
|
||||
|
||||
.Nm Crunchgen
|
||||
reads specifications from the
|
||||
.Ar conf-file
|
||||
that describe the components of the crunched binary. In its simplest
|
||||
use, the component program names are merely listed along with the
|
||||
top-level source directories in which their sources can be found.
|
||||
.Nm Crunchgen
|
||||
then calculates (via the source makefiles) and caches the
|
||||
list of object files and their locations. For more specialized
|
||||
situations, the user can specify by hand all the parameters that
|
||||
.Nm crunchgen
|
||||
needs.
|
||||
.Pp
|
||||
The
|
||||
.Ar conf-file
|
||||
commands are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Nm srcdirs Ar dirname ...
|
||||
A list of source trees in which the source directories of the
|
||||
component programs can be found. These dirs are searched using the
|
||||
BSD ``<source-dir>/<progname>/'' convention. Multiple
|
||||
.Nm srcdirs
|
||||
lines can be specified. The directories are searched in the order
|
||||
they are given.
|
||||
.It Nm progs Ar progname ...
|
||||
A list of programs that make up the crunched binary. Multiple
|
||||
.Nm progs
|
||||
lines can be specified.
|
||||
.It Nm libs Ar libspec ...
|
||||
A list of library specifications to be included in the crunched binary link.
|
||||
Multiple
|
||||
.Nm libs
|
||||
lines can be specified.
|
||||
.It Nm ln Ar progname linkname
|
||||
Causes the crunched binary to invoke
|
||||
.Ar progname
|
||||
whenever
|
||||
.Ar linkname
|
||||
appears in argv[0]. This allows programs that change their behavior when
|
||||
run under different names to operate correctly.
|
||||
.El
|
||||
|
||||
To handle specialized situations, such as when the source is not
|
||||
available or not built via a conventional Makefile, the following
|
||||
.Nm special
|
||||
commands can be used to set
|
||||
.Nm crunchgen
|
||||
parameters for a component program.
|
||||
.Bl -tag -width indent
|
||||
.It Nm special Ar progname Nm srcdir Ar pathname
|
||||
Set the source directory for
|
||||
.Ar progname .
|
||||
This is normally calculated by searching the specified
|
||||
.Nm srcdirs
|
||||
for a directory named
|
||||
.Ar progname .
|
||||
.It Nm special Ar progname Nm objdir Ar pathname
|
||||
Set the obj directory for
|
||||
.Ar progname .
|
||||
This is normally calculated by looking for a directory named
|
||||
.Dq Pa obj
|
||||
under the
|
||||
.Ar srcdir ,
|
||||
and if that is not found, the
|
||||
.Ar srcdir
|
||||
itself becomes the
|
||||
.Ar objdir .
|
||||
.It Nm special Ar progname Nm objs Ar object-file-name ...
|
||||
Set the list of object files for program
|
||||
.Ar progname .
|
||||
This is normally calculated by constructing a temporary makefile that includes
|
||||
.Dq Nm srcdir / Pa Makefile
|
||||
and outputs the value of $(OBJS).
|
||||
.It Nm special Ar progname Nm objpaths Ar full-pathname-to-object-file ...
|
||||
Sets the pathnames of the object files for program
|
||||
.Ar progname .
|
||||
This is normally calculated by prepending the
|
||||
.Nm objdir
|
||||
pathname to each file in the
|
||||
.Nm objs
|
||||
list.
|
||||
.El
|
||||
|
||||
.Pp
|
||||
Only the
|
||||
.Nm objpaths
|
||||
parameter is actually needed by
|
||||
.Nm crunchgen ,
|
||||
but it is calculated from
|
||||
.Nm objdir
|
||||
and
|
||||
.Nm objs ,
|
||||
which are in turn calculated from
|
||||
.Nm srcdir ,
|
||||
so is sometimes convenient to specify the earlier parameters and let
|
||||
.Nm crunchgen
|
||||
calculate forward from there if it can.
|
||||
|
||||
.Pp
|
||||
The makefile produced by
|
||||
.Nm crunchgen
|
||||
contains an optional
|
||||
.Ar objs
|
||||
target that will build the object files for each component program by
|
||||
running make inside that program's source directory. For this to work the
|
||||
.Nm srcdir
|
||||
and
|
||||
.Nm objs
|
||||
parameters must also be valid. If they are not valid for a particular program, that
|
||||
program is skipped in the
|
||||
.Ar objs
|
||||
target.
|
||||
.Sh EXAMPLE
|
||||
Here is an example
|
||||
.Nm crunchgen
|
||||
input conf file, named
|
||||
.Dq Pa kcopy.conf :
|
||||
.Pp
|
||||
.nf
|
||||
srcdirs /usr/src/bin /usr/src/sbin
|
||||
|
||||
progs test cp echo sh fsck halt init mount umount myinstall
|
||||
ln test [ # test can be invoked via [
|
||||
ln sh -sh # init invokes the shell with "-sh" in argv[0]
|
||||
|
||||
special myprog objpaths /homes/leroy/src/myinstall.o # no sources
|
||||
|
||||
libs -lutil -lcrypt
|
||||
.fi
|
||||
.Pp
|
||||
This conf file specifies a small crunched binary consisting of some
|
||||
basic system utilities plus a homegrown install program ``myinstall'',
|
||||
for which no source directory is specified, but its object file is
|
||||
specified directly with the
|
||||
.Nm special
|
||||
line.
|
||||
.Pp
|
||||
The crunched binary ``kcopy'' can be built as follows:
|
||||
.Pp
|
||||
.nf
|
||||
% crunchgen -m Makefile kcopy.conf # gen Makefile and kcopy.c
|
||||
% make objs # build the component progams' .o files
|
||||
% make # build the crunched binary kcopy
|
||||
% kcopy sh # test that this invokes a sh shell
|
||||
$ # it works!
|
||||
.fi
|
||||
.Pp
|
||||
At this point the binary ``kcopy'' can be copied onto an install floppy
|
||||
and hard-linked to the names of the component programs.
|
||||
.Sh SEE ALSO
|
||||
.Xr crunchide 1
|
||||
.Sh CAVEATS
|
||||
While
|
||||
.Nm crunch
|
||||
takes care to eliminate link conflicts between the component programs
|
||||
of a crunched binary, conflicts are still possible between the
|
||||
libraries that are linked in. Some shuffling in the order of
|
||||
libraries may be required, and in some rare cases two libraries may
|
||||
have an unresolveable conflict and thus cannot be crunched together.
|
||||
.Pp
|
||||
Some versions of the BSD build environment do not by default build the
|
||||
intermediate object file for single-source file programs. The ``make
|
||||
objs'' target must then be used to get those object files built, or
|
||||
some other arrangements made.
|
||||
.Sh AUTHOR
|
||||
.Nm Crunch
|
||||
was written by James da Silva <jds@cs.umd.edu>.
|
||||
.sp 0
|
||||
Copyright (c) 1994 University of Maryland. All Rights Reserved.
|
|
@ -0,0 +1,856 @@
|
|||
/*
|
||||
* Copyright (c) 1994 University of Maryland
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of U.M. not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. U.M. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: James da Silva, Systems Design and Analysis Group
|
||||
* Computer Science Department
|
||||
* University of Maryland at College Park
|
||||
*/
|
||||
/*
|
||||
* ========================================================================
|
||||
* crunchgen.c
|
||||
*
|
||||
* Generates a Makefile and main C file for a crunched executable,
|
||||
* from specs given in a .conf file.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#define CRUNCH_VERSION "0.2"
|
||||
|
||||
#define MAXLINELEN 16384
|
||||
#define MAXFIELDS 2048
|
||||
|
||||
|
||||
/* internal representation of conf file: */
|
||||
|
||||
/* simple lists of strings suffice for most parms */
|
||||
|
||||
typedef struct strlst {
|
||||
struct strlst *next;
|
||||
char *str;
|
||||
} strlst_t;
|
||||
|
||||
/* progs have structure, each field can be set with "special" or calculated */
|
||||
|
||||
typedef struct prog {
|
||||
struct prog *next;
|
||||
char *name, *ident;
|
||||
char *srcdir, *objdir;
|
||||
strlst_t *objs, *objpaths;
|
||||
strlst_t *links;
|
||||
int goterror;
|
||||
} prog_t;
|
||||
|
||||
|
||||
/* global state */
|
||||
|
||||
strlst_t *srcdirs = NULL;
|
||||
strlst_t *libs = NULL;
|
||||
prog_t *progs = NULL;
|
||||
|
||||
char line[MAXLINELEN];
|
||||
|
||||
char confname[MAXPATHLEN], infilename[MAXPATHLEN];
|
||||
char outmkname[MAXPATHLEN], outcfname[MAXPATHLEN], execfname[MAXPATHLEN];
|
||||
char tempfname[MAXPATHLEN], cachename[MAXPATHLEN], curfilename[MAXPATHLEN];
|
||||
int linenum = -1;
|
||||
int goterror = 0;
|
||||
|
||||
char *pname = "crunchgen";
|
||||
|
||||
int verbose, readcache; /* options */
|
||||
int reading_cache;
|
||||
|
||||
/* general library routines */
|
||||
|
||||
void status(char *str);
|
||||
void out_of_memory(void);
|
||||
void add_string(strlst_t **listp, char *str);
|
||||
int is_dir(char *pathname);
|
||||
int is_nonempty_file(char *pathname);
|
||||
|
||||
/* helper routines for main() */
|
||||
|
||||
void usage(void);
|
||||
void parse_conf_file(void);
|
||||
void gen_outputs(void);
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *p;
|
||||
int optc;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
verbose = 1;
|
||||
readcache = 1;
|
||||
*outmkname = *outcfname = *execfname = '\0';
|
||||
|
||||
if(argc > 0) pname = argv[0];
|
||||
|
||||
while((optc = getopt(argc, argv, "m:c:e:fq")) != -1) {
|
||||
switch(optc) {
|
||||
case 'f': readcache = 0; break;
|
||||
case 'q': verbose = 0; break;
|
||||
|
||||
case 'm': strcpy(outmkname, optarg); break;
|
||||
case 'c': strcpy(outcfname, optarg); break;
|
||||
case 'e': strcpy(execfname, optarg); break;
|
||||
|
||||
case '?':
|
||||
default: usage();
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if(argc != 1) usage();
|
||||
|
||||
/*
|
||||
* generate filenames
|
||||
*/
|
||||
|
||||
strcpy(infilename, argv[0]);
|
||||
|
||||
/* confname = `basename infilename .conf` */
|
||||
|
||||
if((p=strrchr(infilename, '/')) != NULL) strcpy(confname, p+1);
|
||||
else strcpy(confname, infilename);
|
||||
if((p=strrchr(confname, '.')) != NULL && !strcmp(p, ".conf")) *p = '\0';
|
||||
|
||||
if(!*outmkname) sprintf(outmkname, "%s.mk", confname);
|
||||
if(!*outcfname) sprintf(outcfname, "%s.c", confname);
|
||||
if(!*execfname) sprintf(execfname, "%s", confname);
|
||||
|
||||
sprintf(cachename, "%s.cache", confname);
|
||||
sprintf(tempfname, ".tmp_%sXXXXXX", confname);
|
||||
if(mktemp(tempfname) == NULL) {
|
||||
perror(tempfname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
parse_conf_file();
|
||||
gen_outputs();
|
||||
|
||||
exit(goterror);
|
||||
}
|
||||
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s [-fq] [-m <makefile>] [-c <c file>] [-e <exec file>] <conffile>\n",
|
||||
pname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================================
|
||||
* parse_conf_file subsystem
|
||||
*
|
||||
*/
|
||||
|
||||
/* helper routines for parse_conf_file */
|
||||
|
||||
void parse_one_file(char *filename);
|
||||
void parse_line(char *line, int *fc, char **fv, int nf);
|
||||
void add_srcdirs(int argc, char **argv);
|
||||
void add_progs(int argc, char **argv);
|
||||
void add_link(int argc, char **argv);
|
||||
void add_libs(int argc, char **argv);
|
||||
void add_special(int argc, char **argv);
|
||||
|
||||
prog_t *find_prog(char *str);
|
||||
void add_prog(char *progname);
|
||||
|
||||
|
||||
void parse_conf_file(void)
|
||||
{
|
||||
if(!is_nonempty_file(infilename)) {
|
||||
fprintf(stderr, "%s: fatal: input file \"%s\" not found.\n",
|
||||
pname, infilename);
|
||||
exit(1);
|
||||
}
|
||||
parse_one_file(infilename);
|
||||
if(readcache && is_nonempty_file(cachename)) {
|
||||
reading_cache = 1;
|
||||
parse_one_file(cachename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void parse_one_file(char *filename)
|
||||
{
|
||||
char *fieldv[MAXFIELDS];
|
||||
int fieldc;
|
||||
void (*f)(int c, char **v);
|
||||
FILE *cf;
|
||||
|
||||
sprintf(line, "reading %s", filename);
|
||||
status(line);
|
||||
strcpy(curfilename, filename);
|
||||
|
||||
if((cf = fopen(curfilename, "r")) == NULL) {
|
||||
perror(curfilename);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
linenum = 0;
|
||||
while(fgets(line, MAXLINELEN, cf) != NULL) {
|
||||
linenum++;
|
||||
parse_line(line, &fieldc, fieldv, MAXFIELDS);
|
||||
if(fieldc < 1) continue;
|
||||
if(!strcmp(fieldv[0], "srcdirs")) f = add_srcdirs;
|
||||
else if(!strcmp(fieldv[0], "progs")) f = add_progs;
|
||||
else if(!strcmp(fieldv[0], "ln")) f = add_link;
|
||||
else if(!strcmp(fieldv[0], "libs")) f = add_libs;
|
||||
else if(!strcmp(fieldv[0], "special")) f = add_special;
|
||||
else {
|
||||
fprintf(stderr, "%s:%d: skipping unknown command `%s'.\n",
|
||||
curfilename, linenum, fieldv[0]);
|
||||
goterror = 1;
|
||||
continue;
|
||||
}
|
||||
if(fieldc < 2) {
|
||||
fprintf(stderr,
|
||||
"%s:%d: %s command needs at least 1 argument, skipping.\n",
|
||||
curfilename, linenum, fieldv[0]);
|
||||
goterror = 1;
|
||||
continue;
|
||||
}
|
||||
f(fieldc, fieldv);
|
||||
}
|
||||
|
||||
if(ferror(cf)) {
|
||||
perror(curfilename);
|
||||
goterror = 1;
|
||||
}
|
||||
fclose(cf);
|
||||
}
|
||||
|
||||
|
||||
void parse_line(char *line, int *fc, char **fv, int nf)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = line;
|
||||
*fc = 0;
|
||||
while(1) {
|
||||
while(isspace(*p)) p++;
|
||||
if(*p == '\0' || *p == '#') break;
|
||||
|
||||
if(*fc < nf) fv[(*fc)++] = p;
|
||||
while(*p && !isspace(*p) && *p != '#') p++;
|
||||
if(*p == '\0' || *p == '#') break;
|
||||
*p++ = '\0';
|
||||
}
|
||||
if(*p) *p = '\0'; /* needed for '#' case */
|
||||
}
|
||||
|
||||
|
||||
void add_srcdirs(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=1;i<argc;i++) {
|
||||
if(is_dir(argv[i]))
|
||||
add_string(&srcdirs, argv[i]);
|
||||
else {
|
||||
fprintf(stderr, "%s:%d: `%s' is not a directory, skipping it.\n",
|
||||
curfilename, linenum, argv[i]);
|
||||
goterror = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void add_progs(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=1;i<argc;i++)
|
||||
add_prog(argv[i]);
|
||||
}
|
||||
|
||||
|
||||
void add_prog(char *progname)
|
||||
{
|
||||
prog_t *p1, *p2;
|
||||
|
||||
/* add to end, but be smart about dups */
|
||||
|
||||
for(p1 = NULL, p2 = progs; p2 != NULL; p1 = p2, p2 = p2->next)
|
||||
if(!strcmp(p2->name, progname)) return;
|
||||
|
||||
p2 = malloc(sizeof(prog_t));
|
||||
if(p2) p2->name = strdup(progname);
|
||||
if(!p2 || !p2->name)
|
||||
out_of_memory();
|
||||
|
||||
p2->next = NULL;
|
||||
if(p1 == NULL) progs = p2;
|
||||
else p1->next = p2;
|
||||
|
||||
p2->ident = p2->srcdir = p2->objdir = NULL;
|
||||
p2->links = p2->objs = NULL;
|
||||
p2->goterror = 0;
|
||||
}
|
||||
|
||||
|
||||
void add_link(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
prog_t *p = find_prog(argv[1]);
|
||||
|
||||
if(p == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s:%d: no prog %s previously declared, skipping link.\n",
|
||||
curfilename, linenum, argv[1]);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
for(i=2;i<argc;i++)
|
||||
add_string(&p->links, argv[i]);
|
||||
}
|
||||
|
||||
|
||||
void add_libs(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=1;i<argc;i++)
|
||||
add_string(&libs, argv[i]);
|
||||
}
|
||||
|
||||
|
||||
void add_special(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
prog_t *p = find_prog(argv[1]);
|
||||
|
||||
if(p == NULL) {
|
||||
if(reading_cache) return;
|
||||
fprintf(stderr,
|
||||
"%s:%d: no prog %s previously declared, skipping special.\n",
|
||||
curfilename, linenum, argv[1]);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strcmp(argv[2], "ident")) {
|
||||
if(argc != 4) goto argcount;
|
||||
if((p->ident = strdup(argv[3])) == NULL)
|
||||
out_of_memory();
|
||||
}
|
||||
else if(!strcmp(argv[2], "srcdir")) {
|
||||
if(argc != 4) goto argcount;
|
||||
if((p->srcdir = strdup(argv[3])) == NULL)
|
||||
out_of_memory();
|
||||
}
|
||||
else if(!strcmp(argv[2], "objdir")) {
|
||||
if(argc != 4) goto argcount;
|
||||
if((p->objdir = strdup(argv[3])) == NULL)
|
||||
out_of_memory();
|
||||
}
|
||||
else if(!strcmp(argv[2], "objs")) {
|
||||
p->objs = NULL;
|
||||
for(i=3;i<argc;i++)
|
||||
add_string(&p->objs, argv[i]);
|
||||
}
|
||||
else if(!strcmp(argv[2], "objpaths")) {
|
||||
p->objpaths = NULL;
|
||||
for(i=3;i<argc;i++)
|
||||
add_string(&p->objpaths, argv[i]);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s:%d: bad parameter name `%s', skipping line.\n",
|
||||
curfilename, linenum, argv[2]);
|
||||
goterror = 1;
|
||||
}
|
||||
return;
|
||||
|
||||
|
||||
argcount:
|
||||
fprintf(stderr,
|
||||
"%s:%d: too %s arguments, expected \"special %s %s <string>\".\n",
|
||||
curfilename, linenum, argc < 4? "few" : "many", argv[1], argv[2]);
|
||||
goterror = 1;
|
||||
}
|
||||
|
||||
|
||||
prog_t *find_prog(char *str)
|
||||
{
|
||||
prog_t *p;
|
||||
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
if(!strcmp(p->name, str)) return p;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================================
|
||||
* gen_outputs subsystem
|
||||
*
|
||||
*/
|
||||
|
||||
/* helper subroutines */
|
||||
|
||||
void remove_error_progs(void);
|
||||
void fillin_program(prog_t *p);
|
||||
void gen_specials_cache(void);
|
||||
void gen_output_makefile(void);
|
||||
void gen_output_cfile(void);
|
||||
|
||||
void fillin_program_objs(prog_t *p, char *path);
|
||||
void top_makefile_rules(FILE *outmk);
|
||||
void prog_makefile_rules(FILE *outmk, prog_t *p);
|
||||
void output_strlst(FILE *outf, strlst_t *lst);
|
||||
char *genident(char *str);
|
||||
char *dir_search(char *progname);
|
||||
|
||||
|
||||
void gen_outputs(void)
|
||||
{
|
||||
prog_t *p;
|
||||
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
fillin_program(p);
|
||||
|
||||
remove_error_progs();
|
||||
gen_specials_cache();
|
||||
gen_output_cfile();
|
||||
gen_output_makefile();
|
||||
status("");
|
||||
fprintf(stderr,
|
||||
"Run \"make -f %s objs exe\" to build crunched binary.\n",
|
||||
outmkname);
|
||||
}
|
||||
|
||||
|
||||
void fillin_program(prog_t *p)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
char *srcparent;
|
||||
strlst_t *s;
|
||||
|
||||
sprintf(line, "filling in parms for %s", p->name);
|
||||
status(line);
|
||||
|
||||
if(!p->ident)
|
||||
p->ident = genident(p->name);
|
||||
if(!p->srcdir) {
|
||||
srcparent = dir_search(p->name);
|
||||
if(srcparent)
|
||||
sprintf(path, "%s/%s", srcparent, p->name);
|
||||
if(is_dir(path))
|
||||
p->srcdir = strdup(path);
|
||||
}
|
||||
if(!p->objdir && p->srcdir) {
|
||||
sprintf(path, "%s/obj", p->srcdir);
|
||||
if(is_dir(path))
|
||||
p->objdir = strdup(path);
|
||||
else
|
||||
p->objdir = p->srcdir;
|
||||
}
|
||||
|
||||
if(p->srcdir) sprintf(path, "%s/Makefile", p->srcdir);
|
||||
if(!p->objs && p->srcdir && is_nonempty_file(path))
|
||||
fillin_program_objs(p, path);
|
||||
|
||||
if(!p->objpaths && p->objdir && p->objs)
|
||||
for(s = p->objs; s != NULL; s = s->next) {
|
||||
sprintf(line, "%s/%s", p->objdir, s->str);
|
||||
add_string(&p->objpaths, line);
|
||||
}
|
||||
|
||||
if(!p->srcdir && verbose)
|
||||
fprintf(stderr, "%s: %s: warning: could not find source directory.\n",
|
||||
infilename, p->name);
|
||||
if(!p->objs && verbose)
|
||||
fprintf(stderr, "%s: %s: warning: could not find any .o files.\n",
|
||||
infilename, p->name);
|
||||
|
||||
if(!p->objpaths) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: error: no objpaths specified or calculated.\n",
|
||||
infilename, p->name);
|
||||
p->goterror = goterror = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void fillin_program_objs(prog_t *p, char *path)
|
||||
{
|
||||
char *obj, *cp;
|
||||
int rc;
|
||||
FILE *f;
|
||||
|
||||
/* discover the objs from the srcdir Makefile */
|
||||
|
||||
if((f = fopen(tempfname, "w")) == NULL) {
|
||||
perror(tempfname);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(f, ".include \"%s\"\n", path);
|
||||
fprintf(f, ".if defined(PROG) && !defined(OBJS)\n");
|
||||
fprintf(f, "OBJS=${PROG}.o\n");
|
||||
fprintf(f, ".endif\n");
|
||||
fprintf(f, "crunchgen_objs:\n\t@echo 'OBJS= '${OBJS}\n");
|
||||
fclose(f);
|
||||
|
||||
sprintf(line, "make -f %s crunchgen_objs 2>&1", tempfname);
|
||||
if((f = popen(line, "r")) == NULL) {
|
||||
perror("submake pipe");
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
while(fgets(line, MAXLINELEN, f)) {
|
||||
if(strncmp(line, "OBJS= ", 6)) {
|
||||
fprintf(stderr, "make error: %s", line);
|
||||
goterror = 1;
|
||||
continue;
|
||||
}
|
||||
cp = line + 6;
|
||||
while(isspace(*cp)) cp++;
|
||||
while(*cp) {
|
||||
obj = cp;
|
||||
while(*cp && !isspace(*cp)) cp++;
|
||||
if(*cp) *cp++ = '\0';
|
||||
add_string(&p->objs, obj);
|
||||
while(isspace(*cp)) cp++;
|
||||
}
|
||||
}
|
||||
if((rc=pclose(f)) != 0) {
|
||||
fprintf(stderr, "make error: make returned %d\n", rc);
|
||||
goterror = 1;
|
||||
}
|
||||
unlink(tempfname);
|
||||
}
|
||||
|
||||
void remove_error_progs(void)
|
||||
{
|
||||
prog_t *p1, *p2;
|
||||
|
||||
p1 = NULL; p2 = progs;
|
||||
while(p2 != NULL) {
|
||||
if(!p2->goterror)
|
||||
p1 = p2, p2 = p2->next;
|
||||
else {
|
||||
/* delete it from linked list */
|
||||
fprintf(stderr, "%s: %s: ignoring program because of errors.\n",
|
||||
infilename, p2->name);
|
||||
if(p1) p1->next = p2->next;
|
||||
else progs = p2->next;
|
||||
p2 = p2->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gen_specials_cache(void)
|
||||
{
|
||||
FILE *cachef;
|
||||
prog_t *p;
|
||||
|
||||
sprintf(line, "generating %s", cachename);
|
||||
status(line);
|
||||
|
||||
if((cachef = fopen(cachename, "w")) == NULL) {
|
||||
perror(cachename);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(cachef, "# %s - parm cache generated from %s by crunchgen %s\n\n",
|
||||
cachename, infilename, CRUNCH_VERSION);
|
||||
|
||||
for(p = progs; p != NULL; p = p->next) {
|
||||
fprintf(cachef, "\n");
|
||||
if(p->srcdir)
|
||||
fprintf(cachef, "special %s srcdir %s\n", p->name, p->srcdir);
|
||||
if(p->objdir)
|
||||
fprintf(cachef, "special %s objdir %s\n", p->name, p->objdir);
|
||||
if(p->objs) {
|
||||
fprintf(cachef, "special %s objs", p->name);
|
||||
output_strlst(cachef, p->objs);
|
||||
}
|
||||
fprintf(cachef, "special %s objpaths", p->name);
|
||||
output_strlst(cachef, p->objpaths);
|
||||
}
|
||||
fclose(cachef);
|
||||
}
|
||||
|
||||
|
||||
void gen_output_makefile(void)
|
||||
{
|
||||
prog_t *p;
|
||||
FILE *outmk;
|
||||
|
||||
sprintf(line, "generating %s", outmkname);
|
||||
status(line);
|
||||
|
||||
if((outmk = fopen(outmkname, "w")) == NULL) {
|
||||
perror(outmkname);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(outmk, "# %s - generated from %s by crunchgen %s\n\n",
|
||||
outmkname, infilename, CRUNCH_VERSION);
|
||||
|
||||
top_makefile_rules(outmk);
|
||||
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
prog_makefile_rules(outmk, p);
|
||||
|
||||
fprintf(outmk, "\n# ========\n");
|
||||
fclose(outmk);
|
||||
}
|
||||
|
||||
|
||||
void gen_output_cfile(void)
|
||||
{
|
||||
extern char *crunched_skel[];
|
||||
char **cp;
|
||||
FILE *outcf;
|
||||
prog_t *p;
|
||||
strlst_t *s;
|
||||
|
||||
sprintf(line, "generating %s", outcfname);
|
||||
status(line);
|
||||
|
||||
if((outcf = fopen(outcfname, "w")) == NULL) {
|
||||
perror(outcfname);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(outcf,
|
||||
"/* %s - generated from %s by crunchgen %s */\n",
|
||||
outcfname, infilename, CRUNCH_VERSION);
|
||||
|
||||
fprintf(outcf, "#define EXECNAME \"%s\"\n", execfname);
|
||||
for(cp = crunched_skel; *cp != NULL; cp++)
|
||||
fprintf(outcf, "%s\n", *cp);
|
||||
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
fprintf(outcf, "extern int _crunched_%s_stub();\n", p->ident);
|
||||
|
||||
fprintf(outcf, "\nstruct stub entry_points[] = {\n");
|
||||
for(p = progs; p != NULL; p = p->next) {
|
||||
fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
|
||||
p->name, p->ident);
|
||||
for(s = p->links; s != NULL; s = s->next)
|
||||
fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
|
||||
s->str, p->ident);
|
||||
}
|
||||
|
||||
fprintf(outcf, "\t{ EXECNAME, crunched_main },\n");
|
||||
fprintf(outcf, "\t{ NULL, NULL }\n};\n");
|
||||
fclose(outcf);
|
||||
}
|
||||
|
||||
|
||||
char *genident(char *str)
|
||||
{
|
||||
char *n,*s,*d;
|
||||
|
||||
/*
|
||||
* generates a Makefile/C identifier from a program name, mapping '-' to
|
||||
* '_' and ignoring all other non-identifier characters. This leads to
|
||||
* programs named "foo.bar" and "foobar" to map to the same identifier.
|
||||
*/
|
||||
|
||||
if((n = strdup(str)) == NULL)
|
||||
return NULL;
|
||||
for(d = s = n; *s != '\0'; s++) {
|
||||
if(*s == '-') *d++ = '_';
|
||||
else if(*s == '_' || isalnum(*s)) *d++ = *s;
|
||||
}
|
||||
*d = '\0';
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
char *dir_search(char *progname)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
strlst_t *dir;
|
||||
|
||||
for(dir=srcdirs; dir != NULL; dir=dir->next) {
|
||||
sprintf(path, "%s/%s", dir->str, progname);
|
||||
if(is_dir(path)) return dir->str;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void top_makefile_rules(FILE *outmk)
|
||||
{
|
||||
prog_t *p;
|
||||
|
||||
fprintf(outmk, "LIBS=");
|
||||
output_strlst(outmk, libs);
|
||||
|
||||
fprintf(outmk, "CRUNCHED_OBJS=");
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
fprintf(outmk, " %s.lo", p->name);
|
||||
fprintf(outmk, "\n");
|
||||
|
||||
fprintf(outmk, "SUBMAKE_TARGETS=");
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
fprintf(outmk, " %s_make", p->ident);
|
||||
fprintf(outmk, "\n\n");
|
||||
|
||||
fprintf(outmk, "%s: %s.o $(CRUNCHED_OBJS)\n",
|
||||
execfname, execfname);
|
||||
fprintf(outmk, "\t$(CC) -static -o %s %s.o $(CRUNCHED_OBJS) $(LIBS)\n",
|
||||
execfname, execfname);
|
||||
fprintf(outmk, "\tstrip %s\n", execfname);
|
||||
fprintf(outmk, "all: objs exe\nobjs: $(SUBMAKE_TARGETS)\n");
|
||||
fprintf(outmk, "exe: %s\n", execfname);
|
||||
fprintf(outmk, "clean:\n\trm -f %s *.lo *.o *_stub.c\n",
|
||||
execfname);
|
||||
}
|
||||
|
||||
|
||||
void prog_makefile_rules(FILE *outmk, prog_t *p)
|
||||
{
|
||||
fprintf(outmk, "\n# -------- %s\n\n", p->name);
|
||||
|
||||
if(p->srcdir && p->objs) {
|
||||
fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir);
|
||||
fprintf(outmk, "%s_OBJS=", p->ident);
|
||||
output_strlst(outmk, p->objs);
|
||||
fprintf(outmk, "%s_make:\n", p->ident);
|
||||
fprintf(outmk, "\t(cd $(%s_SRCDIR); make $(%s_OBJS))\n\n",
|
||||
p->ident, p->ident);
|
||||
}
|
||||
else
|
||||
fprintf(outmk, "%s_make:\n\t@echo \"** cannot make objs for %s\"\n\n",
|
||||
p->ident, p->name);
|
||||
|
||||
fprintf(outmk, "%s_OBJPATHS=", p->ident);
|
||||
output_strlst(outmk, p->objpaths);
|
||||
|
||||
fprintf(outmk, "%s_stub.c:\n", p->name);
|
||||
fprintf(outmk, "\techo \""
|
||||
"int _crunched_%s_stub(int argc, char **argv, char **envp)"
|
||||
"{return main(argc,argv,envp);}\" >%s_stub.c\n",
|
||||
p->ident, p->name);
|
||||
fprintf(outmk, "%s.lo: %s_stub.o $(%s_OBJPATHS)\n",
|
||||
p->name, p->name, p->ident);
|
||||
fprintf(outmk, "\tld -dc -r -o %s.lo %s_stub.o $(%s_OBJPATHS)\n",
|
||||
p->name, p->name, p->ident);
|
||||
fprintf(outmk, "\tcrunchide -k __crunched_%s_stub %s.lo\n",
|
||||
p->ident, p->name);
|
||||
}
|
||||
|
||||
void output_strlst(FILE *outf, strlst_t *lst)
|
||||
{
|
||||
for(; lst != NULL; lst = lst->next)
|
||||
fprintf(outf, " %s", lst->str);
|
||||
fprintf(outf, "\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================================
|
||||
* general library routines
|
||||
*
|
||||
*/
|
||||
|
||||
void status(char *str)
|
||||
{
|
||||
static int lastlen = 0;
|
||||
int len, spaces;
|
||||
|
||||
if(!verbose) return;
|
||||
|
||||
len = strlen(str);
|
||||
spaces = lastlen - len;
|
||||
if(spaces < 1) spaces = 1;
|
||||
|
||||
fprintf(stderr, " [%s]%*.*s\r", str, spaces, spaces, " ");
|
||||
fflush(stderr);
|
||||
lastlen = len;
|
||||
}
|
||||
|
||||
|
||||
void out_of_memory(void)
|
||||
{
|
||||
fprintf(stderr, "%s: %d: out of memory, stopping.\n", infilename, linenum);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void add_string(strlst_t **listp, char *str)
|
||||
{
|
||||
strlst_t *p1, *p2;
|
||||
|
||||
/* add to end, but be smart about dups */
|
||||
|
||||
for(p1 = NULL, p2 = *listp; p2 != NULL; p1 = p2, p2 = p2->next)
|
||||
if(!strcmp(p2->str, str)) return;
|
||||
|
||||
p2 = malloc(sizeof(strlst_t));
|
||||
if(p2) p2->str = strdup(str);
|
||||
if(!p2 || !p2->str)
|
||||
out_of_memory();
|
||||
|
||||
p2->next = NULL;
|
||||
if(p1 == NULL) *listp = p2;
|
||||
else p1->next = p2;
|
||||
}
|
||||
|
||||
|
||||
int is_dir(char *pathname)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if(stat(pathname, &buf) == -1)
|
||||
return 0;
|
||||
return S_ISDIR(buf.st_mode);
|
||||
}
|
||||
|
||||
int is_nonempty_file(char *pathname)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if(stat(pathname, &buf) == -1)
|
||||
return 0;
|
||||
|
||||
return S_ISREG(buf.st_mode) && buf.st_size > 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#! /bin/sh
|
||||
# idea and sed lines taken straight from flex
|
||||
|
||||
cat <<!EOF
|
||||
/* File created via mkskel.sh */
|
||||
|
||||
char *crunched_skel[] = {
|
||||
!EOF
|
||||
|
||||
sed 's/\\/&&/g' $* | sed 's/"/\\"/g' | sed 's/.*/ "&",/'
|
||||
|
||||
cat <<!EOF
|
||||
0
|
||||
};
|
||||
!EOF
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
PROG= crunchide
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,70 @@
|
|||
.\"
|
||||
.\" Copyright (c) 1994 University of Maryland
|
||||
.\" All Rights Reserved.
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, distribute, and sell this software and its
|
||||
.\" documentation for any purpose is hereby granted without fee, provided that
|
||||
.\" the above copyright notice appear in all copies and that both that
|
||||
.\" copyright notice and this permission notice appear in supporting
|
||||
.\" documentation, and that the name of U.M. not be used in advertising or
|
||||
.\" publicity pertaining to distribution of the software without specific,
|
||||
.\" written prior permission. U.M. makes no representations about the
|
||||
.\" suitability of this software for any purpose. It is provided "as is"
|
||||
.\" without express or implied warranty.
|
||||
.\"
|
||||
.\" U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
.\" BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
.\" IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.\" Author: James da Silva, Systems Design and Analysis Group
|
||||
.\" Computer Science Department
|
||||
.\" University of Maryland at College Park
|
||||
.\"
|
||||
.Dd June 14, 1994
|
||||
.Dt CRUNCHIDE 1
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm crunchide
|
||||
.Nd hides symbol names from ld, for crunching programs together
|
||||
.Sh SYNOPSIS
|
||||
.Nm crunchide
|
||||
.Op Fl f Ar keep-list-file
|
||||
.Op Fl k Ar keep-symbol
|
||||
.Op Ar object-file ...
|
||||
.Sh DESCRIPTION
|
||||
|
||||
.Nm Crunchide
|
||||
hides the global symbols of
|
||||
.Ar object-file
|
||||
such that they are ignored by subsequent runs of the linker,
|
||||
.Xr ld 1 .
|
||||
Some symbols may be left visible via the
|
||||
.Fl k Ar keep-symbol
|
||||
and
|
||||
.Fl f Ar keep-list-file
|
||||
options. The
|
||||
.Ar keep-list-file
|
||||
must contain a list of symbols to keep visible, one symbol per line.
|
||||
Note that the C compiler prepends an underscore in front of
|
||||
symbols, so to keep the C function ``foo'' visible, the option
|
||||
\&``-k _foo'' must be used.
|
||||
|
||||
.Pp
|
||||
.Nm Crunchide
|
||||
is designed as a companion program for
|
||||
.Xr crunchgen 1 ,
|
||||
which automates the process of creating crunched binaries from
|
||||
multiple component programs.
|
||||
.Sh SEE ALSO
|
||||
.Xr crunchgen 1 ,
|
||||
.Xr ld 1
|
||||
.Sh BUGS
|
||||
Should have just used symorder -t where available.
|
||||
.Sh AUTHOR
|
||||
.Nm Crunch
|
||||
was written by James da Silva <jds@cs.umd.edu>.
|
||||
.sp 0
|
||||
Copyright (c) 1994 University of Maryland. All Rights Reserved.
|
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
* Copyright (c) 1994 University of Maryland
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of U.M. not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. U.M. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: James da Silva, Systems Design and Analysis Group
|
||||
* Computer Science Department
|
||||
* University of Maryland at College Park
|
||||
*/
|
||||
/*
|
||||
* crunchide.c - tiptoes through an a.out symbol table, hiding all defined
|
||||
* global symbols. Allows the user to supply a "keep list" of symbols
|
||||
* that are not to be hidden. This program relies on the use of the
|
||||
* linker's -dc flag to actually put global bss data into the file's
|
||||
* bss segment (rather than leaving it as undefined "common" data).
|
||||
*
|
||||
* The point of all this is to allow multiple programs to be linked
|
||||
* together without getting multiple-defined errors.
|
||||
*
|
||||
* For example, consider a program "foo.c". It can be linked with a
|
||||
* small stub routine, called "foostub.c", eg:
|
||||
* int foo_main(int argc, char **argv){ return main(argc, argv); }
|
||||
* like so:
|
||||
* cc -c foo.c foostub.c
|
||||
* ld -dc -r foo.o foostub.o -o foo.combined.o
|
||||
* crunchide -k _foo_main foo.combined.o
|
||||
* at this point, foo.combined.o can be linked with another program
|
||||
* and invoked with "foo_main(argc, argv)". foo's main() and any
|
||||
* other globals are hidden and will not conflict with other symbols.
|
||||
*
|
||||
* TODO:
|
||||
* - resolve the theoretical hanging reloc problem (see check_reloc()
|
||||
* below). I have yet to see this problem actually occur in any real
|
||||
* program. In what cases will gcc/gas generate code that needs a
|
||||
* relative reloc from a global symbol, other than PIC? The
|
||||
* solution is to not hide the symbol from the linker in this case,
|
||||
* but to generate some random name for it so that it doesn't link
|
||||
* with anything but holds the place for the reloc.
|
||||
* - arrange that all the BSS segments start at the same address, so
|
||||
* that the final crunched binary BSS size is the max of all the
|
||||
* component programs' BSS sizes, rather than their sum.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <a.out.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
char *pname = "crunchide";
|
||||
|
||||
void usage(void);
|
||||
|
||||
void add_to_keep_list(char *symbol);
|
||||
void add_file_to_keep_list(char *filename);
|
||||
|
||||
void hide_syms(char *filename);
|
||||
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int ch;
|
||||
|
||||
if(argc > 0) pname = argv[0];
|
||||
|
||||
while ((ch = getopt(argc, argv, "k:f:")) != EOF)
|
||||
switch(ch) {
|
||||
case 'k':
|
||||
add_to_keep_list(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
add_file_to_keep_list(optarg);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if(argc == 0) usage();
|
||||
|
||||
while(argc) {
|
||||
hide_syms(*argv);
|
||||
argc--, argv++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-k <symbol-name>] [-f <keep-list-file>] <files> ...\n",
|
||||
pname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* ---------------------------- */
|
||||
|
||||
struct keep {
|
||||
struct keep *next;
|
||||
char *sym;
|
||||
} *keep_list;
|
||||
|
||||
void add_to_keep_list(char *symbol)
|
||||
{
|
||||
struct keep *newp, *prevp, *curp;
|
||||
int cmp;
|
||||
|
||||
for(curp = keep_list, prevp = NULL; curp; prevp = curp, curp = curp->next)
|
||||
if((cmp = strcmp(symbol, curp->sym)) <= 0) break;
|
||||
|
||||
if(curp && cmp == 0)
|
||||
return; /* already in table */
|
||||
|
||||
newp = (struct keep *) malloc(sizeof(struct keep));
|
||||
if(newp) newp->sym = strdup(symbol);
|
||||
if(newp == NULL || newp->sym == NULL) {
|
||||
fprintf(stderr, "%s: out of memory for keep list\n", pname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
newp->next = curp;
|
||||
if(prevp) prevp->next = newp;
|
||||
else keep_list = newp;
|
||||
}
|
||||
|
||||
int in_keep_list(char *symbol)
|
||||
{
|
||||
struct keep *curp;
|
||||
int cmp;
|
||||
|
||||
for(curp = keep_list; curp; curp = curp->next)
|
||||
if((cmp = strcmp(symbol, curp->sym)) <= 0) break;
|
||||
|
||||
return curp && cmp == 0;
|
||||
}
|
||||
|
||||
void add_file_to_keep_list(char *filename)
|
||||
{
|
||||
FILE *keepf;
|
||||
char symbol[1024];
|
||||
int len;
|
||||
|
||||
if((keepf = fopen(filename, "r")) == NULL) {
|
||||
perror(filename);
|
||||
usage();
|
||||
}
|
||||
|
||||
while(fgets(symbol, 1024, keepf)) {
|
||||
len = strlen(symbol);
|
||||
if(len && symbol[len-1] == '\n')
|
||||
symbol[len-1] = '\0';
|
||||
|
||||
add_to_keep_list(symbol);
|
||||
}
|
||||
fclose(keepf);
|
||||
}
|
||||
|
||||
/* ---------------------- */
|
||||
|
||||
int nsyms, ntextrel, ndatarel;
|
||||
struct exec *hdrp;
|
||||
char *aoutdata, *strbase;
|
||||
struct relocation_info *textrel, *datarel;
|
||||
struct nlist *symbase;
|
||||
|
||||
|
||||
#define SYMSTR(sp) &strbase[(sp)->n_un.n_strx]
|
||||
|
||||
/* is the symbol a global symbol defined in the current file? */
|
||||
#define IS_GLOBAL_DEFINED(sp) \
|
||||
(((sp)->n_type & N_EXT) && ((sp)->n_type & N_TYPE) != N_UNDF)
|
||||
|
||||
/* is the relocation entry dependent on a symbol? */
|
||||
#define IS_SYMBOL_RELOC(rp) \
|
||||
((rp)->r_extern||(rp)->r_baserel||(rp)->r_jmptable)
|
||||
|
||||
void check_reloc(char *filename, struct relocation_info *relp);
|
||||
|
||||
void hide_syms(char *filename)
|
||||
{
|
||||
int inf, outf, rc;
|
||||
struct stat infstat;
|
||||
struct relocation_info *relp;
|
||||
struct nlist *symp;
|
||||
|
||||
/*
|
||||
* Open the file and do some error checking.
|
||||
*/
|
||||
|
||||
if((inf = open(filename, O_RDWR)) == -1) {
|
||||
perror(filename);
|
||||
return;
|
||||
}
|
||||
|
||||
if(fstat(inf, &infstat) == -1) {
|
||||
perror(filename);
|
||||
close(inf);
|
||||
return;
|
||||
}
|
||||
|
||||
if(infstat.st_size < sizeof(struct exec)) {
|
||||
fprintf(stderr, "%s: short file\n", filename);
|
||||
close(inf);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the entire file into memory. XXX - Really, we only need to
|
||||
* read the header and from TRELOFF to the end of the file.
|
||||
*/
|
||||
|
||||
if((aoutdata = (char *) malloc(infstat.st_size)) == NULL) {
|
||||
fprintf(stderr, "%s: too big to read into memory\n", filename);
|
||||
close(inf);
|
||||
return;
|
||||
}
|
||||
|
||||
if((rc = read(inf, aoutdata, infstat.st_size)) < infstat.st_size) {
|
||||
fprintf(stderr, "%s: read error: %s\n", filename,
|
||||
rc == -1? strerror(errno) : "short read");
|
||||
close(inf);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the header and calculate offsets and sizes from it.
|
||||
*/
|
||||
|
||||
hdrp = (struct exec *) aoutdata;
|
||||
|
||||
if(N_BADMAG(*hdrp)) {
|
||||
fprintf(stderr, "%s: bad magic: not an a.out file\n", filename);
|
||||
close(inf);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
textrel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp));
|
||||
datarel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp) +
|
||||
hdrp->a_trsize);
|
||||
#else
|
||||
textrel = (struct relocation_info *) (aoutdata + N_TRELOFF(*hdrp));
|
||||
datarel = (struct relocation_info *) (aoutdata + N_DRELOFF(*hdrp));
|
||||
#endif
|
||||
symbase = (struct nlist *) (aoutdata + N_SYMOFF(*hdrp));
|
||||
strbase = (char *) (aoutdata + N_STROFF(*hdrp));
|
||||
|
||||
ntextrel = hdrp->a_trsize / sizeof(struct relocation_info);
|
||||
ndatarel = hdrp->a_drsize / sizeof(struct relocation_info);
|
||||
nsyms = hdrp->a_syms / sizeof(struct nlist);
|
||||
|
||||
/*
|
||||
* Zap the type field of all globally-defined symbols. The linker will
|
||||
* subsequently ignore these entries. Don't zap any symbols in the
|
||||
* keep list.
|
||||
*/
|
||||
|
||||
for(symp = symbase; symp < symbase + nsyms; symp++)
|
||||
if(IS_GLOBAL_DEFINED(symp) && !in_keep_list(SYMSTR(symp)))
|
||||
symp->n_type = 0;
|
||||
|
||||
/*
|
||||
* Check whether the relocation entries reference any symbols that we
|
||||
* just zapped. I don't know whether ld can handle this case, but I
|
||||
* haven't encountered it yet. These checks are here so that the program
|
||||
* doesn't fail silently should such symbols be encountered.
|
||||
*/
|
||||
|
||||
for(relp = textrel; relp < textrel + ntextrel; relp++)
|
||||
check_reloc(filename, relp);
|
||||
for(relp = datarel; relp < datarel + ndatarel; relp++)
|
||||
check_reloc(filename, relp);
|
||||
|
||||
/*
|
||||
* Write the .o file back out to disk. XXX - Really, we only need to
|
||||
* write the symbol table entries back out.
|
||||
*/
|
||||
lseek(inf, 0, SEEK_SET);
|
||||
if((rc = write(inf, aoutdata, infstat.st_size)) < infstat.st_size) {
|
||||
fprintf(stderr, "%s: write error: %s\n", filename,
|
||||
rc == -1? strerror(errno) : "short write");
|
||||
}
|
||||
|
||||
close(inf);
|
||||
}
|
||||
|
||||
|
||||
void check_reloc(char *filename, struct relocation_info *relp)
|
||||
{
|
||||
/* bail out if we zapped a symbol that is needed */
|
||||
if(IS_SYMBOL_RELOC(relp) && symbase[relp->r_symbolnum].n_type == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: oops, have hanging relocation for %s: bailing out!\n",
|
||||
filename, SYMSTR(&symbase[relp->r_symbolnum]));
|
||||
exit(1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
CRUNCHED= fixit
|
||||
|
||||
# below is boiler-plate to make $(CRUNCHED) from $(CRUNCHED).conf
|
||||
# I'd use PROG instead of CRUNCHED, but the system makefiles REALLY want
|
||||
# to build things in the normal way if you use PROG.
|
||||
|
||||
CONF= $(CRUNCHED).conf
|
||||
|
||||
OUTMK= $(CRUNCHED).mk
|
||||
OUTPUTS= $(OUTMK) $(CRUNCHED).c $(CRUNCHED).cache
|
||||
|
||||
NOMAN=
|
||||
CLEANFILES+=$(CRUNCHED) $(OUTPUTS) *.o *.lo *_stub.c
|
||||
|
||||
all: $(CRUNCHED)
|
||||
exe: $(CRUNCHED)
|
||||
|
||||
$(OUTPUTS): $(CONF)
|
||||
crunchgen ${.CURDIR}/$(CONF)
|
||||
|
||||
$(CRUNCHED): $(OUTPUTS) submake
|
||||
|
||||
submake:
|
||||
make -f $(OUTMK)
|
||||
objs:
|
||||
make -f $(OUTMK) objs
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,44 @@
|
|||
# fixit.conf - put in anything we think we might want on a fixit floppy
|
||||
|
||||
# first, we list the source dirs that our programs reside in. These are
|
||||
# searched in order listed to find the dir containing each program.
|
||||
|
||||
srcdirs /usr/src/bin /usr/src/sbin /usr/src/usr.bin /usr/src/usr.sbin
|
||||
srcdirs /usr/src/gnu/usr.bin
|
||||
|
||||
# second, we list all the programs we want to include in our crunched binary.
|
||||
# The order doesn't matter. Any program that needs hard links to it gets an
|
||||
# `ln' directive.
|
||||
|
||||
# /bin stuff
|
||||
|
||||
progs cat chmod cp date dd df echo ed expr hostname kill ln ls mkdir
|
||||
progs mt mv pwd rcp rm rmdir sh sleep stty sync test
|
||||
|
||||
ln test [
|
||||
ln sh -sh # init invokes the shell this way
|
||||
ln sh -
|
||||
|
||||
# /sbin stuff
|
||||
|
||||
progs badsect chown clri disklabel dump dmesg fdisk fsck halt ifconfig init
|
||||
progs mknod mount newfs ping reboot restore swapon umount
|
||||
ln dump rdump
|
||||
ln restore rrestore
|
||||
|
||||
# /usr/bin stuff
|
||||
|
||||
progs ftp rsh sed telnet rlogin vi
|
||||
|
||||
# gnu stuff
|
||||
|
||||
progs cpio gzip
|
||||
ln gzip gunzip
|
||||
ln gzip gzcat
|
||||
|
||||
# finally, we specify the libraries to link in with our binary
|
||||
|
||||
libs -ledit # NetBSDism
|
||||
libs -lcrypt # but don't include this when exporting :-(
|
||||
libs -lcurses -ltermcap
|
||||
libs -lkvm -ltelnet -lutil -ll
|
|
@ -0,0 +1,26 @@
|
|||
# $Id: freebsd-filesystem.conf,v 1.1.1.1 1994/08/29 14:47:30 cgd Exp $
|
||||
|
||||
srcdirs /usr/src/bin /usr/src/sbin /usr/src/gnu/usr.bin /usr/src/usr.sbin
|
||||
|
||||
# /bin
|
||||
progs sh expr ls mkdir rm sync test
|
||||
ln test [
|
||||
|
||||
# These are needed because of UN*X's idiotic way of indicating that something
|
||||
# is a login shell.
|
||||
ln sh -
|
||||
ln sh -sh
|
||||
|
||||
# /sbin
|
||||
progs disklabel fdisk halt init mount mount_pcfs newfs umount
|
||||
|
||||
# /usr/bin
|
||||
progs cpio gzip
|
||||
ln gzip gunzip
|
||||
ln gzip gzcat
|
||||
ln gzip zcat
|
||||
|
||||
# /usr/sbin
|
||||
progs bad144
|
||||
|
||||
libs -lutil
|
|
@ -0,0 +1,18 @@
|
|||
# $Id: freebsd-kcopy.conf,v 1.1.1.1 1994/08/29 14:47:30 cgd Exp $
|
||||
|
||||
srcdirs /usr/src/bin /usr/src/sbin
|
||||
|
||||
# Programs from bin/
|
||||
progs sh cp echo test
|
||||
ln test [
|
||||
|
||||
# These are needed because of UN*X's idiotic way of indicating that something
|
||||
# is a login shell.
|
||||
ln sh -
|
||||
ln sh -sh
|
||||
|
||||
#
|
||||
# Programs from sbin/
|
||||
progs mount mount_isofs mount_pcfs fsck halt init umount
|
||||
|
||||
libs -lutil
|
|
@ -0,0 +1,146 @@
|
|||
# really-big.conf - just about everything, just for testing.
|
||||
# This ends up having some good examples of the use of specials for
|
||||
# those hard-to-reach programs. I stopped when I got tired, but we
|
||||
# could probably get even more stuff (like libexec stuff) in here.
|
||||
#
|
||||
# This produces a 4608000 byte binary. Pretty sick and twisted, eh?
|
||||
|
||||
# =========================================================================
|
||||
|
||||
srcdirs /usr/src/bin
|
||||
|
||||
progs cat chmod cp csh date dd df domainname echo ed expr hostname kill
|
||||
progs ln ls mkdir mt mv ps pwd rcp rm rmail rmdir sh sleep stty sync test
|
||||
|
||||
ln test [
|
||||
ln sh -sh
|
||||
|
||||
|
||||
# =========================================================================
|
||||
|
||||
srcdirs /usr/src/sbin
|
||||
|
||||
progs badsect bim clri disklabel dmesg dump dumpfs fdisk fsck halt
|
||||
progs ifconfig init mknod modload modunload mount mount_fdesc mount_isofs
|
||||
progs mount_kernfs mount_lofs mount_msdos mount_portal mount_procfs mountd
|
||||
progs newfs nfsd nfsiod ping quotacheck reboot restore route routed savecore
|
||||
progs shutdown slattach swapon ttyflags tunefs umount
|
||||
# shell scripts: fastboot
|
||||
|
||||
ln dump rdump
|
||||
ln restore rrestore
|
||||
|
||||
|
||||
# =========================================================================
|
||||
|
||||
srcdirs /usr/src/usr.bin
|
||||
|
||||
progs apropos ar asa at basename biff cal calendar cap_mkdb checknr chpass
|
||||
progs cksum cmp col colcrt colrm column comm compress crontab ctags cut
|
||||
progs dirname du env error expand false file find finger fmt fold fpr from
|
||||
progs fsplit fstat ftp getconf getopt gprof head hexdump id indent ipcrm
|
||||
progs ipcs join kdump ktrace last lastcomm leave lex lock logger locate
|
||||
progs login logname look m4 machine mail make man mesg mkfifo
|
||||
progs mkstr modstat more msgs netstat newsyslog nfsstat nice nm nohup
|
||||
progs pagesize passwd paste patch pr printenv printf quota ranlib
|
||||
progs renice rev rlogin rpcgen rpcinfo rsh rup ruptime rusers rwall rwho
|
||||
progs script sed showmount size soelim split strings strip su tail talk
|
||||
progs tcopy tee telnet tftp time tip tn3270 touch tput tr true tset tsort
|
||||
progs tty ul uname unexpand unifdef uniq units unvis users uudecode uuencode
|
||||
progs vacation vgrind vi vis vmstat w wall wc what whatis whereis who
|
||||
progs whois window write xargs xinstall xstr yacc yes ypcat ypmatch ypwhich
|
||||
|
||||
# shell scripts: lorder mkdep shar which
|
||||
# problems: rdist uses libcompat.a(regex.o), which conflicts with
|
||||
# libedit(readline.o) over regerror().
|
||||
|
||||
# special requirements
|
||||
|
||||
special locate srcdir /usr/src/usr.bin/locate/locate
|
||||
special tn3270 srcdir /usr/src/usr.bin/tn3270/tn3270
|
||||
|
||||
|
||||
# =========================================================================
|
||||
|
||||
srcdirs /usr/src/usr.sbin
|
||||
|
||||
progs ac accton amd arp bad144 catman chown chroot config config.new cron
|
||||
progs dev_mkdb diskpart edquota flcopy gettable grfinfo hilinfo htable inetd
|
||||
progs iostat iteconfig kvm_mkdb mrouted mtree named portmap pppd
|
||||
progs pstat pwd_mkdb quot quotaon rarpd rbootd repquota rmt rpc.bootparamd
|
||||
progs rwhod sa sliplogin slstats spray sysctl syslogd tcpdump
|
||||
progs traceroute trpt trsp update vipw vnconfig ypbind yppoll ypset
|
||||
|
||||
special amd srcdir /usr/src/usr.sbin/amd/amd
|
||||
special amd objs vers.amd.o afs_ops.o am_ops.o clock.o util.o xutil.o efs_ops.o mapc.o info_file.o info_hes.o info_ndbm.o info_passwd.o info_nis.o info_union.o map.o srvr_afs.o srvr_nfs.o mntfs.o misc_rpc.o mount_fs.o mtab.o mtab_bsd.o nfs_ops.o nfs_prot_svc.o nfs_start.o nfs_subr.o opts.o pfs_ops.o rpc_fwd.o sched.o sfs_ops.o amq_svc.o amq_subr.o umount_fs.o host_ops.o nfsx_ops.o ufs_ops.o ifs_ops.o amd.o get_args.o restart.o wire.o
|
||||
|
||||
|
||||
srcdirs /usr/src/usr.sbin/lpr # lpr subsystem
|
||||
progs lpr lpc lpq lprm pac lptest
|
||||
special lpr srcdir /usr/src/usr.sbin/lpr/lpr
|
||||
|
||||
srcdirs /usr/src/usr.sbin/sendmail # sendmail subsystem
|
||||
progs mailstats makemap praliases sendmail
|
||||
special sendmail srcdir /usr/src/usr.sbin/sendmail/src
|
||||
ln sendmail newaliases
|
||||
ln sendmail mailq
|
||||
|
||||
srcdirs /usr/src/usr.sbin/timed # timed & timedc
|
||||
progs timed timedc
|
||||
special timed srcdir /usr/src/usr.sbin/timed/timed
|
||||
|
||||
srcdirs /usr/src/usr.sbin/yp # yp subsystem
|
||||
progs ypbind ypwhich ypcat ypmatch ypset yppoll
|
||||
|
||||
|
||||
# =========================================================================
|
||||
|
||||
srcdirs /usr/src/gnu/usr.bin
|
||||
|
||||
progs bc cpio diff diff3 gas gawk grep gzip sdiff sort tar
|
||||
# shell scripts: send-pr
|
||||
|
||||
srcdirs /usr/src/gnu/usr.bin/ld # ldd and ldconfig
|
||||
progs ld ldd ldconfig
|
||||
|
||||
# rcs stuff loses because there are cross dependencies between librcs.a and
|
||||
# the individual programs. The solution would be to specify the objpaths
|
||||
# directly for each one, and include the full path to librcs.a each the
|
||||
# objpaths.
|
||||
|
||||
# srcdirs /usr/src/gnu/usr.bin/rcs # rcs subsystem
|
||||
# progs ci co ident merge rcs rcsclean rcsdiff rcsmerge rlog
|
||||
# # shell script: rcsfreeze
|
||||
# special rcs srcdir /usr/src/gnu/usr.bin/rcs/rcs
|
||||
# libs /usr/src/gnu/usr.bin/rcs/lib/obj/librcs.a
|
||||
|
||||
# gdb loses too
|
||||
# progs gdb
|
||||
# special gdb srcdir /usr/src/gnu/usr.bin/gdb/gdb
|
||||
# libs /usr/src/gnu/usr.bin/gdb/bfd/obj/libbfd.a
|
||||
# libs /usr/src/gnu/usr.bin/gdb/readline/obj/libreadline.a
|
||||
# libs /usr/src/gnu/usr.bin/gdb/libiberty/obj/libiberty.a
|
||||
|
||||
# groff has the same problem as rcs
|
||||
# srcdirs /usr/src/gnu/usr.bin/groff # groff subsystem
|
||||
# progs groff troff tbl pic eqn grops grotty grodvi refer lookbib
|
||||
# progs indxbib lkbib tfmtodit addftinfo pfbtops psbb
|
||||
# shell script: nroff
|
||||
# special groff srcdir /usr/src/gnu/usr.bin/groff/groff
|
||||
# libs /usr/src/gnu/usr.bin/groff/libgroff/obj/libgroff.a
|
||||
# libs /usr/src/gnu/usr.bin/groff/libbib/obj/libbib.a
|
||||
# libs /usr/src/gnu/usr.bin/groff/libdriver/obj/libdriver.a
|
||||
|
||||
srcdirs /usr/src/gnu/usr.bin/gcc2 # gcc & friends
|
||||
progs cc cpp cc1
|
||||
|
||||
# cc1 has the same problem as rcs and groff, but since there's only one program
|
||||
# I'll go ahead and solve it as an example.
|
||||
|
||||
special cc1 objpaths /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-parse.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-lang.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-lex.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-pragma.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-decl.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-typeck.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-convert.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-aux-info.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-iterate.o /usr/src/gnu/usr.bin/gcc2/common/obj/libcc1.a
|
||||
|
||||
ln gzip gunzip
|
||||
ln gzip gzcat
|
||||
|
||||
libs -ledit -lgnumalloc -lc -lcrypt -ltermcap -lcurses -ltelnet -lutil -lkvm
|
||||
libs -ll -ly -lm -lresolv -lrpcsvc -lcompat
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 1994 University of Maryland
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of U.M. not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. U.M. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: James da Silva, Systems Design and Analysis Group
|
||||
* Computer Science Department
|
||||
* University of Maryland at College Park
|
||||
*/
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
SUBDIR=crunchgen crunchide
|
||||
|
||||
.include <bsd.subdir.mk>
|
|
@ -0,0 +1,2 @@
|
|||
# modify to taste
|
||||
BINDIR?= /usr/local/bin
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
CRUNCH 0.3 README 7/23/94
|
||||
|
||||
Crunch is available via anonymous ftp to ftp.cs.umd.edu in
|
||||
pub/bsd/crunch-0.3.tar.gz
|
||||
|
||||
WHAT'S NEW IN 0.3
|
||||
|
||||
* The prototype awk script has been replaced by a more capable and
|
||||
hopefully more robust C program.
|
||||
* No fragile template makefiles or dependencies on the details of the
|
||||
bsd build environment.
|
||||
* You can build crunched binaries even with no sources on-line, you
|
||||
just need the .o files. Crunchgen still will try to figure out as
|
||||
much as possible on its own, but you can override its guessing by
|
||||
specifying the list of .o files explicitly.
|
||||
* Crunch itself has been bmake'd and some man pages written, so it
|
||||
should be ready to install.
|
||||
* Added patch for FreeBSD from Jordan Hubbard, plus the .conf files used
|
||||
for the FreeBSD install floppies as examples.
|
||||
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
Crunch is a little package that helps create "crunched" binaries for use
|
||||
on boot, install, and fixit floppies. A crunched binary in this case is
|
||||
one where many programs have been linked together into one a.out file.
|
||||
The different programs are run depending on the value of argv[0], so
|
||||
hard links to the crunched binary suffice to simulate a perfectly normal
|
||||
system.
|
||||
|
||||
As an example, I have created an 980K crunched "fixit" binary containing
|
||||
the following programs in their entirety:
|
||||
|
||||
cat chmod cp date dd df echo ed expr hostname kill ln ls mkdir
|
||||
mt mv pwd rcp rm rmdir sh sleep stty sync test [ badsect chown
|
||||
clri disklabel dump rdump dmesg fdisk fsck halt ifconfig init
|
||||
mknod mount newfs ping reboot restore rrestore swapon umount
|
||||
ftp rsh sed telnet rlogin vi cpio gzip gunzip gzcat
|
||||
|
||||
Note carefully: vi, cpio, gzip, ed, sed, dump/restore, some networking
|
||||
utilities, and the disk management utilities, all in a binary small
|
||||
enough to fit on a 1.2 MB root filesystem floppy (albeit with the kernel
|
||||
on its own boot floppy). A more reasonable subset can be made to fit
|
||||
easily with a kernel for a decent one-disk fixit filesystem.
|
||||
|
||||
The linking together of different programs by hand is an old
|
||||
space-saving technique. Crunch automates the process by building the
|
||||
necessary stub files and makefile for you (via the crunchgen program),
|
||||
and by doctoring the symbol tables of the component .o files to allow
|
||||
them to link without "symbol multiply defined" conflicts (via the
|
||||
crunchide program).
|
||||
|
||||
|
||||
BUILDING CRUNCH
|
||||
|
||||
Just type make, then make install.
|
||||
|
||||
Crunch was written and tested under NetBSD/i386, but should work under
|
||||
other PC BSD systems that use GNU ld.
|
||||
|
||||
The crunchgen(1) and crunchide(1) man pages have more details on using
|
||||
crunch, and the examples subdirectory contains some working .conf files
|
||||
and a sample Makefile.
|
||||
|
||||
CREDITS
|
||||
|
||||
Thanks to the NetBSD team for a consistently high quality effort in
|
||||
bringing together a solid, state of the art development environment.
|
||||
|
||||
Thanks to the FreeBSD guys; Rod Grimes, Nate Williams and Jordan
|
||||
Hubbard; and to Bruce Evans, for immediate and detailed feedback on
|
||||
crunch 0.1, and for pressing me to make the prototype more useable.
|
||||
|
||||
Crunch was written for the Maruti Hard Real-Time Operating System
|
||||
project at the University of Maryland, to help make for better install
|
||||
and recovery procedures for our NetBSD-based development environment. It
|
||||
is copyright (c) 1994 by the University of Maryland under a UCB-style
|
||||
freely- redistributable notice. See the file COPYRIGHT for details.
|
||||
|
||||
Please let me know of any problems or of enhancements you make to this
|
||||
package. I'm particularly interested in the details of what you found
|
||||
was good to put on your fixit or install disks. Thanks!
|
||||
|
||||
Share and Enjoy,
|
||||
Jaime
|
||||
............................................................................
|
||||
: Stand on my shoulders, : jds@cs.umd.edu : James da Silva
|
||||
: not on my toes. : uunet!mimsy!jds : http://www.cs.umd.edu/users/jds
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
PROG=crunchgen
|
||||
SRCS=crunchgen.c crunched_skel.c
|
||||
CFLAGS+=-g -Wall
|
||||
CLEANFILES+= crunched_skel.c
|
||||
|
||||
crunched_skel.c: crunched_main.c
|
||||
${.CURDIR}/mkskel.sh ${.CURDIR}/crunched_main.c >crunched_skel.c
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 1994 University of Maryland
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of U.M. not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. U.M. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: James da Silva, Systems Design and Analysis Group
|
||||
* Computer Science Department
|
||||
* University of Maryland at College Park
|
||||
*/
|
||||
/*
|
||||
* crunched_main.c - main program for crunched binaries, it branches to a
|
||||
* particular subprogram based on the value of argv[0]. Also included
|
||||
* is a little program invoked when the crunched binary is called via
|
||||
* its EXECNAME. This one prints out the list of compiled-in binaries,
|
||||
* or calls one of them based on argv[1]. This allows the testing of
|
||||
* the crunched binary without creating all the links.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
struct stub {
|
||||
char *name;
|
||||
int (*f)();
|
||||
};
|
||||
|
||||
extern struct stub entry_points[];
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *slash, *basename;
|
||||
struct stub *ep;
|
||||
|
||||
if(argv[0] == NULL || *argv[0] == '\0')
|
||||
crunched_usage();
|
||||
|
||||
slash = strrchr(argv[0], '/');
|
||||
basename = slash? slash+1 : argv[0];
|
||||
|
||||
for(ep=entry_points; ep->name != NULL; ep++)
|
||||
if(!strcmp(basename, ep->name)) break;
|
||||
|
||||
if(ep->name)
|
||||
return ep->f(argc, argv);
|
||||
else {
|
||||
fprintf(stderr, "%s: %s not compiled in\n", EXECNAME, basename);
|
||||
crunched_usage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int crunched_main(int argc, char **argv)
|
||||
{
|
||||
struct stub *ep;
|
||||
int columns, len;
|
||||
|
||||
if(argc <= 1)
|
||||
crunched_usage();
|
||||
|
||||
return main(--argc, ++argv);
|
||||
}
|
||||
|
||||
|
||||
int crunched_usage()
|
||||
{
|
||||
int columns, len;
|
||||
struct stub *ep;
|
||||
|
||||
fprintf(stderr, "Usage: %s <prog> <args> ..., where <prog> is one of:\n",
|
||||
EXECNAME);
|
||||
columns = 0;
|
||||
for(ep=entry_points; ep->name != NULL; ep++) {
|
||||
len = strlen(ep->name) + 1;
|
||||
if(columns+len < 80)
|
||||
columns += len;
|
||||
else {
|
||||
fprintf(stderr, "\n");
|
||||
columns = len;
|
||||
}
|
||||
fprintf(stderr, " %s", ep->name);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* end of crunched_main.c */
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
.\"
|
||||
.\" Copyright (c) 1994 University of Maryland
|
||||
.\" All Rights Reserved.
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, distribute, and sell this software and its
|
||||
.\" documentation for any purpose is hereby granted without fee, provided that
|
||||
.\" the above copyright notice appear in all copies and that both that
|
||||
.\" copyright notice and this permission notice appear in supporting
|
||||
.\" documentation, and that the name of U.M. not be used in advertising or
|
||||
.\" publicity pertaining to distribution of the software without specific,
|
||||
.\" written prior permission. U.M. makes no representations about the
|
||||
.\" suitability of this software for any purpose. It is provided "as is"
|
||||
.\" without express or implied warranty.
|
||||
.\"
|
||||
.\" U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
.\" BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
.\" IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.\" Author: James da Silva, Systems Design and Analysis Group
|
||||
.\" Computer Science Department
|
||||
.\" University of Maryland at College Park
|
||||
.\"
|
||||
.Dd June 14, 1994
|
||||
.Dt CRUNCHGEN 1
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm \&crunchgen
|
||||
.Nd generates build environment for a crunched binary
|
||||
.Sh SYNOPSIS
|
||||
.Nm \&crunchgen
|
||||
.Op Fl fq
|
||||
.Op Fl m Ar makefile-name
|
||||
.Op Fl c Ar c-file-name
|
||||
.Op Fl e Ar exec-file-name
|
||||
.Op Ar conf-file
|
||||
.Sh DESCRIPTION
|
||||
|
||||
A crunched binary is a program made up of many other programs linked
|
||||
together into a single executable. The crunched binary main()
|
||||
function determines which component program to run by the contents of
|
||||
argv[0]. The main reason to crunch programs together is for fitting
|
||||
as many programs as possible onto an installation or system recovery
|
||||
floppy.
|
||||
|
||||
.Pp
|
||||
.Nm Crunchgen
|
||||
reads in the specifications in
|
||||
.Ar conf-file
|
||||
for a crunched binary, and generates a Makefile and accompanying
|
||||
top-level C source file that when built create the crunched executable
|
||||
file from the component programs. For each component program,
|
||||
.Nm crunchgen
|
||||
can optionally attempt to determine the object (.o) files that make up
|
||||
the program from its source directory Makefile. This information is
|
||||
cached between runs.
|
||||
.Nm Crunchgen
|
||||
uses the companion program
|
||||
.Nm crunchide
|
||||
to eliminate link-time conflicts between the component programs by
|
||||
hiding all unnecessary symbols.
|
||||
|
||||
.Pp
|
||||
After
|
||||
.Nm crunchgen
|
||||
is run, the crunched binary can be built by running ``make -f
|
||||
<conf-name>.mk''. The component programs' object files must already
|
||||
be built. A ``objs'' target, included in the output makefile, will
|
||||
run make in each component program's source dir to build the object
|
||||
files for the user. This is not done automatically since in release
|
||||
engineering circumstances it is generally not desireable to be
|
||||
modifying objects in other directories.
|
||||
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl c Ar c-file-name
|
||||
Set output C file name to
|
||||
.Ar c-file-name .
|
||||
The default name is ``<conf-name>.c''.
|
||||
.It Fl e Ar exec-file-name
|
||||
Set crunched binary executable file name to
|
||||
.Ar exec-file-name .
|
||||
The default name is ``<conf-name>''.
|
||||
.It Fl f
|
||||
Flush cache. Forces the recalculation of cached parameters.
|
||||
.It Fl m Ar makefile-name
|
||||
Set output Makefile name to
|
||||
.Ar makefile-name .
|
||||
The default name is ``<conf-name>.mk''.
|
||||
.It Fl q
|
||||
Quiet operation. Status messages are suppressed.
|
||||
.El
|
||||
.Sh CRUNCHGEN CONFIGURATION FILE COMMANDS
|
||||
|
||||
.Nm Crunchgen
|
||||
reads specifications from the
|
||||
.Ar conf-file
|
||||
that describe the components of the crunched binary. In its simplest
|
||||
use, the component program names are merely listed along with the
|
||||
top-level source directories in which their sources can be found.
|
||||
.Nm Crunchgen
|
||||
then calculates (via the source makefiles) and caches the
|
||||
list of object files and their locations. For more specialized
|
||||
situations, the user can specify by hand all the parameters that
|
||||
.Nm crunchgen
|
||||
needs.
|
||||
.Pp
|
||||
The
|
||||
.Ar conf-file
|
||||
commands are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Nm srcdirs Ar dirname ...
|
||||
A list of source trees in which the source directories of the
|
||||
component programs can be found. These dirs are searched using the
|
||||
BSD ``<source-dir>/<progname>/'' convention. Multiple
|
||||
.Nm srcdirs
|
||||
lines can be specified. The directories are searched in the order
|
||||
they are given.
|
||||
.It Nm progs Ar progname ...
|
||||
A list of programs that make up the crunched binary. Multiple
|
||||
.Nm progs
|
||||
lines can be specified.
|
||||
.It Nm libs Ar libspec ...
|
||||
A list of library specifications to be included in the crunched binary link.
|
||||
Multiple
|
||||
.Nm libs
|
||||
lines can be specified.
|
||||
.It Nm ln Ar progname linkname
|
||||
Causes the crunched binary to invoke
|
||||
.Ar progname
|
||||
whenever
|
||||
.Ar linkname
|
||||
appears in argv[0]. This allows programs that change their behavior when
|
||||
run under different names to operate correctly.
|
||||
.El
|
||||
|
||||
To handle specialized situations, such as when the source is not
|
||||
available or not built via a conventional Makefile, the following
|
||||
.Nm special
|
||||
commands can be used to set
|
||||
.Nm crunchgen
|
||||
parameters for a component program.
|
||||
.Bl -tag -width indent
|
||||
.It Nm special Ar progname Nm srcdir Ar pathname
|
||||
Set the source directory for
|
||||
.Ar progname .
|
||||
This is normally calculated by searching the specified
|
||||
.Nm srcdirs
|
||||
for a directory named
|
||||
.Ar progname .
|
||||
.It Nm special Ar progname Nm objdir Ar pathname
|
||||
Set the obj directory for
|
||||
.Ar progname .
|
||||
This is normally calculated by looking for a directory named
|
||||
.Dq Pa obj
|
||||
under the
|
||||
.Ar srcdir ,
|
||||
and if that is not found, the
|
||||
.Ar srcdir
|
||||
itself becomes the
|
||||
.Ar objdir .
|
||||
.It Nm special Ar progname Nm objs Ar object-file-name ...
|
||||
Set the list of object files for program
|
||||
.Ar progname .
|
||||
This is normally calculated by constructing a temporary makefile that includes
|
||||
.Dq Nm srcdir / Pa Makefile
|
||||
and outputs the value of $(OBJS).
|
||||
.It Nm special Ar progname Nm objpaths Ar full-pathname-to-object-file ...
|
||||
Sets the pathnames of the object files for program
|
||||
.Ar progname .
|
||||
This is normally calculated by prepending the
|
||||
.Nm objdir
|
||||
pathname to each file in the
|
||||
.Nm objs
|
||||
list.
|
||||
.El
|
||||
|
||||
.Pp
|
||||
Only the
|
||||
.Nm objpaths
|
||||
parameter is actually needed by
|
||||
.Nm crunchgen ,
|
||||
but it is calculated from
|
||||
.Nm objdir
|
||||
and
|
||||
.Nm objs ,
|
||||
which are in turn calculated from
|
||||
.Nm srcdir ,
|
||||
so is sometimes convenient to specify the earlier parameters and let
|
||||
.Nm crunchgen
|
||||
calculate forward from there if it can.
|
||||
|
||||
.Pp
|
||||
The makefile produced by
|
||||
.Nm crunchgen
|
||||
contains an optional
|
||||
.Ar objs
|
||||
target that will build the object files for each component program by
|
||||
running make inside that program's source directory. For this to work the
|
||||
.Nm srcdir
|
||||
and
|
||||
.Nm objs
|
||||
parameters must also be valid. If they are not valid for a particular program, that
|
||||
program is skipped in the
|
||||
.Ar objs
|
||||
target.
|
||||
.Sh EXAMPLE
|
||||
Here is an example
|
||||
.Nm crunchgen
|
||||
input conf file, named
|
||||
.Dq Pa kcopy.conf :
|
||||
.Pp
|
||||
.nf
|
||||
srcdirs /usr/src/bin /usr/src/sbin
|
||||
|
||||
progs test cp echo sh fsck halt init mount umount myinstall
|
||||
ln test [ # test can be invoked via [
|
||||
ln sh -sh # init invokes the shell with "-sh" in argv[0]
|
||||
|
||||
special myprog objpaths /homes/leroy/src/myinstall.o # no sources
|
||||
|
||||
libs -lutil -lcrypt
|
||||
.fi
|
||||
.Pp
|
||||
This conf file specifies a small crunched binary consisting of some
|
||||
basic system utilities plus a homegrown install program ``myinstall'',
|
||||
for which no source directory is specified, but its object file is
|
||||
specified directly with the
|
||||
.Nm special
|
||||
line.
|
||||
.Pp
|
||||
The crunched binary ``kcopy'' can be built as follows:
|
||||
.Pp
|
||||
.nf
|
||||
% crunchgen -m Makefile kcopy.conf # gen Makefile and kcopy.c
|
||||
% make objs # build the component progams' .o files
|
||||
% make # build the crunched binary kcopy
|
||||
% kcopy sh # test that this invokes a sh shell
|
||||
$ # it works!
|
||||
.fi
|
||||
.Pp
|
||||
At this point the binary ``kcopy'' can be copied onto an install floppy
|
||||
and hard-linked to the names of the component programs.
|
||||
.Sh SEE ALSO
|
||||
.Xr crunchide 1
|
||||
.Sh CAVEATS
|
||||
While
|
||||
.Nm crunch
|
||||
takes care to eliminate link conflicts between the component programs
|
||||
of a crunched binary, conflicts are still possible between the
|
||||
libraries that are linked in. Some shuffling in the order of
|
||||
libraries may be required, and in some rare cases two libraries may
|
||||
have an unresolveable conflict and thus cannot be crunched together.
|
||||
.Pp
|
||||
Some versions of the BSD build environment do not by default build the
|
||||
intermediate object file for single-source file programs. The ``make
|
||||
objs'' target must then be used to get those object files built, or
|
||||
some other arrangements made.
|
||||
.Sh AUTHOR
|
||||
.Nm Crunch
|
||||
was written by James da Silva <jds@cs.umd.edu>.
|
||||
.sp 0
|
||||
Copyright (c) 1994 University of Maryland. All Rights Reserved.
|
|
@ -0,0 +1,856 @@
|
|||
/*
|
||||
* Copyright (c) 1994 University of Maryland
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of U.M. not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. U.M. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: James da Silva, Systems Design and Analysis Group
|
||||
* Computer Science Department
|
||||
* University of Maryland at College Park
|
||||
*/
|
||||
/*
|
||||
* ========================================================================
|
||||
* crunchgen.c
|
||||
*
|
||||
* Generates a Makefile and main C file for a crunched executable,
|
||||
* from specs given in a .conf file.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#define CRUNCH_VERSION "0.2"
|
||||
|
||||
#define MAXLINELEN 16384
|
||||
#define MAXFIELDS 2048
|
||||
|
||||
|
||||
/* internal representation of conf file: */
|
||||
|
||||
/* simple lists of strings suffice for most parms */
|
||||
|
||||
typedef struct strlst {
|
||||
struct strlst *next;
|
||||
char *str;
|
||||
} strlst_t;
|
||||
|
||||
/* progs have structure, each field can be set with "special" or calculated */
|
||||
|
||||
typedef struct prog {
|
||||
struct prog *next;
|
||||
char *name, *ident;
|
||||
char *srcdir, *objdir;
|
||||
strlst_t *objs, *objpaths;
|
||||
strlst_t *links;
|
||||
int goterror;
|
||||
} prog_t;
|
||||
|
||||
|
||||
/* global state */
|
||||
|
||||
strlst_t *srcdirs = NULL;
|
||||
strlst_t *libs = NULL;
|
||||
prog_t *progs = NULL;
|
||||
|
||||
char line[MAXLINELEN];
|
||||
|
||||
char confname[MAXPATHLEN], infilename[MAXPATHLEN];
|
||||
char outmkname[MAXPATHLEN], outcfname[MAXPATHLEN], execfname[MAXPATHLEN];
|
||||
char tempfname[MAXPATHLEN], cachename[MAXPATHLEN], curfilename[MAXPATHLEN];
|
||||
int linenum = -1;
|
||||
int goterror = 0;
|
||||
|
||||
char *pname = "crunchgen";
|
||||
|
||||
int verbose, readcache; /* options */
|
||||
int reading_cache;
|
||||
|
||||
/* general library routines */
|
||||
|
||||
void status(char *str);
|
||||
void out_of_memory(void);
|
||||
void add_string(strlst_t **listp, char *str);
|
||||
int is_dir(char *pathname);
|
||||
int is_nonempty_file(char *pathname);
|
||||
|
||||
/* helper routines for main() */
|
||||
|
||||
void usage(void);
|
||||
void parse_conf_file(void);
|
||||
void gen_outputs(void);
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *p;
|
||||
int optc;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
verbose = 1;
|
||||
readcache = 1;
|
||||
*outmkname = *outcfname = *execfname = '\0';
|
||||
|
||||
if(argc > 0) pname = argv[0];
|
||||
|
||||
while((optc = getopt(argc, argv, "m:c:e:fq")) != -1) {
|
||||
switch(optc) {
|
||||
case 'f': readcache = 0; break;
|
||||
case 'q': verbose = 0; break;
|
||||
|
||||
case 'm': strcpy(outmkname, optarg); break;
|
||||
case 'c': strcpy(outcfname, optarg); break;
|
||||
case 'e': strcpy(execfname, optarg); break;
|
||||
|
||||
case '?':
|
||||
default: usage();
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if(argc != 1) usage();
|
||||
|
||||
/*
|
||||
* generate filenames
|
||||
*/
|
||||
|
||||
strcpy(infilename, argv[0]);
|
||||
|
||||
/* confname = `basename infilename .conf` */
|
||||
|
||||
if((p=strrchr(infilename, '/')) != NULL) strcpy(confname, p+1);
|
||||
else strcpy(confname, infilename);
|
||||
if((p=strrchr(confname, '.')) != NULL && !strcmp(p, ".conf")) *p = '\0';
|
||||
|
||||
if(!*outmkname) sprintf(outmkname, "%s.mk", confname);
|
||||
if(!*outcfname) sprintf(outcfname, "%s.c", confname);
|
||||
if(!*execfname) sprintf(execfname, "%s", confname);
|
||||
|
||||
sprintf(cachename, "%s.cache", confname);
|
||||
sprintf(tempfname, ".tmp_%sXXXXXX", confname);
|
||||
if(mktemp(tempfname) == NULL) {
|
||||
perror(tempfname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
parse_conf_file();
|
||||
gen_outputs();
|
||||
|
||||
exit(goterror);
|
||||
}
|
||||
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s [-fq] [-m <makefile>] [-c <c file>] [-e <exec file>] <conffile>\n",
|
||||
pname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================================
|
||||
* parse_conf_file subsystem
|
||||
*
|
||||
*/
|
||||
|
||||
/* helper routines for parse_conf_file */
|
||||
|
||||
void parse_one_file(char *filename);
|
||||
void parse_line(char *line, int *fc, char **fv, int nf);
|
||||
void add_srcdirs(int argc, char **argv);
|
||||
void add_progs(int argc, char **argv);
|
||||
void add_link(int argc, char **argv);
|
||||
void add_libs(int argc, char **argv);
|
||||
void add_special(int argc, char **argv);
|
||||
|
||||
prog_t *find_prog(char *str);
|
||||
void add_prog(char *progname);
|
||||
|
||||
|
||||
void parse_conf_file(void)
|
||||
{
|
||||
if(!is_nonempty_file(infilename)) {
|
||||
fprintf(stderr, "%s: fatal: input file \"%s\" not found.\n",
|
||||
pname, infilename);
|
||||
exit(1);
|
||||
}
|
||||
parse_one_file(infilename);
|
||||
if(readcache && is_nonempty_file(cachename)) {
|
||||
reading_cache = 1;
|
||||
parse_one_file(cachename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void parse_one_file(char *filename)
|
||||
{
|
||||
char *fieldv[MAXFIELDS];
|
||||
int fieldc;
|
||||
void (*f)(int c, char **v);
|
||||
FILE *cf;
|
||||
|
||||
sprintf(line, "reading %s", filename);
|
||||
status(line);
|
||||
strcpy(curfilename, filename);
|
||||
|
||||
if((cf = fopen(curfilename, "r")) == NULL) {
|
||||
perror(curfilename);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
linenum = 0;
|
||||
while(fgets(line, MAXLINELEN, cf) != NULL) {
|
||||
linenum++;
|
||||
parse_line(line, &fieldc, fieldv, MAXFIELDS);
|
||||
if(fieldc < 1) continue;
|
||||
if(!strcmp(fieldv[0], "srcdirs")) f = add_srcdirs;
|
||||
else if(!strcmp(fieldv[0], "progs")) f = add_progs;
|
||||
else if(!strcmp(fieldv[0], "ln")) f = add_link;
|
||||
else if(!strcmp(fieldv[0], "libs")) f = add_libs;
|
||||
else if(!strcmp(fieldv[0], "special")) f = add_special;
|
||||
else {
|
||||
fprintf(stderr, "%s:%d: skipping unknown command `%s'.\n",
|
||||
curfilename, linenum, fieldv[0]);
|
||||
goterror = 1;
|
||||
continue;
|
||||
}
|
||||
if(fieldc < 2) {
|
||||
fprintf(stderr,
|
||||
"%s:%d: %s command needs at least 1 argument, skipping.\n",
|
||||
curfilename, linenum, fieldv[0]);
|
||||
goterror = 1;
|
||||
continue;
|
||||
}
|
||||
f(fieldc, fieldv);
|
||||
}
|
||||
|
||||
if(ferror(cf)) {
|
||||
perror(curfilename);
|
||||
goterror = 1;
|
||||
}
|
||||
fclose(cf);
|
||||
}
|
||||
|
||||
|
||||
void parse_line(char *line, int *fc, char **fv, int nf)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = line;
|
||||
*fc = 0;
|
||||
while(1) {
|
||||
while(isspace(*p)) p++;
|
||||
if(*p == '\0' || *p == '#') break;
|
||||
|
||||
if(*fc < nf) fv[(*fc)++] = p;
|
||||
while(*p && !isspace(*p) && *p != '#') p++;
|
||||
if(*p == '\0' || *p == '#') break;
|
||||
*p++ = '\0';
|
||||
}
|
||||
if(*p) *p = '\0'; /* needed for '#' case */
|
||||
}
|
||||
|
||||
|
||||
void add_srcdirs(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=1;i<argc;i++) {
|
||||
if(is_dir(argv[i]))
|
||||
add_string(&srcdirs, argv[i]);
|
||||
else {
|
||||
fprintf(stderr, "%s:%d: `%s' is not a directory, skipping it.\n",
|
||||
curfilename, linenum, argv[i]);
|
||||
goterror = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void add_progs(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=1;i<argc;i++)
|
||||
add_prog(argv[i]);
|
||||
}
|
||||
|
||||
|
||||
void add_prog(char *progname)
|
||||
{
|
||||
prog_t *p1, *p2;
|
||||
|
||||
/* add to end, but be smart about dups */
|
||||
|
||||
for(p1 = NULL, p2 = progs; p2 != NULL; p1 = p2, p2 = p2->next)
|
||||
if(!strcmp(p2->name, progname)) return;
|
||||
|
||||
p2 = malloc(sizeof(prog_t));
|
||||
if(p2) p2->name = strdup(progname);
|
||||
if(!p2 || !p2->name)
|
||||
out_of_memory();
|
||||
|
||||
p2->next = NULL;
|
||||
if(p1 == NULL) progs = p2;
|
||||
else p1->next = p2;
|
||||
|
||||
p2->ident = p2->srcdir = p2->objdir = NULL;
|
||||
p2->links = p2->objs = NULL;
|
||||
p2->goterror = 0;
|
||||
}
|
||||
|
||||
|
||||
void add_link(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
prog_t *p = find_prog(argv[1]);
|
||||
|
||||
if(p == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s:%d: no prog %s previously declared, skipping link.\n",
|
||||
curfilename, linenum, argv[1]);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
for(i=2;i<argc;i++)
|
||||
add_string(&p->links, argv[i]);
|
||||
}
|
||||
|
||||
|
||||
void add_libs(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=1;i<argc;i++)
|
||||
add_string(&libs, argv[i]);
|
||||
}
|
||||
|
||||
|
||||
void add_special(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
prog_t *p = find_prog(argv[1]);
|
||||
|
||||
if(p == NULL) {
|
||||
if(reading_cache) return;
|
||||
fprintf(stderr,
|
||||
"%s:%d: no prog %s previously declared, skipping special.\n",
|
||||
curfilename, linenum, argv[1]);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strcmp(argv[2], "ident")) {
|
||||
if(argc != 4) goto argcount;
|
||||
if((p->ident = strdup(argv[3])) == NULL)
|
||||
out_of_memory();
|
||||
}
|
||||
else if(!strcmp(argv[2], "srcdir")) {
|
||||
if(argc != 4) goto argcount;
|
||||
if((p->srcdir = strdup(argv[3])) == NULL)
|
||||
out_of_memory();
|
||||
}
|
||||
else if(!strcmp(argv[2], "objdir")) {
|
||||
if(argc != 4) goto argcount;
|
||||
if((p->objdir = strdup(argv[3])) == NULL)
|
||||
out_of_memory();
|
||||
}
|
||||
else if(!strcmp(argv[2], "objs")) {
|
||||
p->objs = NULL;
|
||||
for(i=3;i<argc;i++)
|
||||
add_string(&p->objs, argv[i]);
|
||||
}
|
||||
else if(!strcmp(argv[2], "objpaths")) {
|
||||
p->objpaths = NULL;
|
||||
for(i=3;i<argc;i++)
|
||||
add_string(&p->objpaths, argv[i]);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s:%d: bad parameter name `%s', skipping line.\n",
|
||||
curfilename, linenum, argv[2]);
|
||||
goterror = 1;
|
||||
}
|
||||
return;
|
||||
|
||||
|
||||
argcount:
|
||||
fprintf(stderr,
|
||||
"%s:%d: too %s arguments, expected \"special %s %s <string>\".\n",
|
||||
curfilename, linenum, argc < 4? "few" : "many", argv[1], argv[2]);
|
||||
goterror = 1;
|
||||
}
|
||||
|
||||
|
||||
prog_t *find_prog(char *str)
|
||||
{
|
||||
prog_t *p;
|
||||
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
if(!strcmp(p->name, str)) return p;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================================
|
||||
* gen_outputs subsystem
|
||||
*
|
||||
*/
|
||||
|
||||
/* helper subroutines */
|
||||
|
||||
void remove_error_progs(void);
|
||||
void fillin_program(prog_t *p);
|
||||
void gen_specials_cache(void);
|
||||
void gen_output_makefile(void);
|
||||
void gen_output_cfile(void);
|
||||
|
||||
void fillin_program_objs(prog_t *p, char *path);
|
||||
void top_makefile_rules(FILE *outmk);
|
||||
void prog_makefile_rules(FILE *outmk, prog_t *p);
|
||||
void output_strlst(FILE *outf, strlst_t *lst);
|
||||
char *genident(char *str);
|
||||
char *dir_search(char *progname);
|
||||
|
||||
|
||||
void gen_outputs(void)
|
||||
{
|
||||
prog_t *p;
|
||||
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
fillin_program(p);
|
||||
|
||||
remove_error_progs();
|
||||
gen_specials_cache();
|
||||
gen_output_cfile();
|
||||
gen_output_makefile();
|
||||
status("");
|
||||
fprintf(stderr,
|
||||
"Run \"make -f %s objs exe\" to build crunched binary.\n",
|
||||
outmkname);
|
||||
}
|
||||
|
||||
|
||||
void fillin_program(prog_t *p)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
char *srcparent;
|
||||
strlst_t *s;
|
||||
|
||||
sprintf(line, "filling in parms for %s", p->name);
|
||||
status(line);
|
||||
|
||||
if(!p->ident)
|
||||
p->ident = genident(p->name);
|
||||
if(!p->srcdir) {
|
||||
srcparent = dir_search(p->name);
|
||||
if(srcparent)
|
||||
sprintf(path, "%s/%s", srcparent, p->name);
|
||||
if(is_dir(path))
|
||||
p->srcdir = strdup(path);
|
||||
}
|
||||
if(!p->objdir && p->srcdir) {
|
||||
sprintf(path, "%s/obj", p->srcdir);
|
||||
if(is_dir(path))
|
||||
p->objdir = strdup(path);
|
||||
else
|
||||
p->objdir = p->srcdir;
|
||||
}
|
||||
|
||||
if(p->srcdir) sprintf(path, "%s/Makefile", p->srcdir);
|
||||
if(!p->objs && p->srcdir && is_nonempty_file(path))
|
||||
fillin_program_objs(p, path);
|
||||
|
||||
if(!p->objpaths && p->objdir && p->objs)
|
||||
for(s = p->objs; s != NULL; s = s->next) {
|
||||
sprintf(line, "%s/%s", p->objdir, s->str);
|
||||
add_string(&p->objpaths, line);
|
||||
}
|
||||
|
||||
if(!p->srcdir && verbose)
|
||||
fprintf(stderr, "%s: %s: warning: could not find source directory.\n",
|
||||
infilename, p->name);
|
||||
if(!p->objs && verbose)
|
||||
fprintf(stderr, "%s: %s: warning: could not find any .o files.\n",
|
||||
infilename, p->name);
|
||||
|
||||
if(!p->objpaths) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: error: no objpaths specified or calculated.\n",
|
||||
infilename, p->name);
|
||||
p->goterror = goterror = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void fillin_program_objs(prog_t *p, char *path)
|
||||
{
|
||||
char *obj, *cp;
|
||||
int rc;
|
||||
FILE *f;
|
||||
|
||||
/* discover the objs from the srcdir Makefile */
|
||||
|
||||
if((f = fopen(tempfname, "w")) == NULL) {
|
||||
perror(tempfname);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(f, ".include \"%s\"\n", path);
|
||||
fprintf(f, ".if defined(PROG) && !defined(OBJS)\n");
|
||||
fprintf(f, "OBJS=${PROG}.o\n");
|
||||
fprintf(f, ".endif\n");
|
||||
fprintf(f, "crunchgen_objs:\n\t@echo 'OBJS= '${OBJS}\n");
|
||||
fclose(f);
|
||||
|
||||
sprintf(line, "make -f %s crunchgen_objs 2>&1", tempfname);
|
||||
if((f = popen(line, "r")) == NULL) {
|
||||
perror("submake pipe");
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
while(fgets(line, MAXLINELEN, f)) {
|
||||
if(strncmp(line, "OBJS= ", 6)) {
|
||||
fprintf(stderr, "make error: %s", line);
|
||||
goterror = 1;
|
||||
continue;
|
||||
}
|
||||
cp = line + 6;
|
||||
while(isspace(*cp)) cp++;
|
||||
while(*cp) {
|
||||
obj = cp;
|
||||
while(*cp && !isspace(*cp)) cp++;
|
||||
if(*cp) *cp++ = '\0';
|
||||
add_string(&p->objs, obj);
|
||||
while(isspace(*cp)) cp++;
|
||||
}
|
||||
}
|
||||
if((rc=pclose(f)) != 0) {
|
||||
fprintf(stderr, "make error: make returned %d\n", rc);
|
||||
goterror = 1;
|
||||
}
|
||||
unlink(tempfname);
|
||||
}
|
||||
|
||||
void remove_error_progs(void)
|
||||
{
|
||||
prog_t *p1, *p2;
|
||||
|
||||
p1 = NULL; p2 = progs;
|
||||
while(p2 != NULL) {
|
||||
if(!p2->goterror)
|
||||
p1 = p2, p2 = p2->next;
|
||||
else {
|
||||
/* delete it from linked list */
|
||||
fprintf(stderr, "%s: %s: ignoring program because of errors.\n",
|
||||
infilename, p2->name);
|
||||
if(p1) p1->next = p2->next;
|
||||
else progs = p2->next;
|
||||
p2 = p2->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gen_specials_cache(void)
|
||||
{
|
||||
FILE *cachef;
|
||||
prog_t *p;
|
||||
|
||||
sprintf(line, "generating %s", cachename);
|
||||
status(line);
|
||||
|
||||
if((cachef = fopen(cachename, "w")) == NULL) {
|
||||
perror(cachename);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(cachef, "# %s - parm cache generated from %s by crunchgen %s\n\n",
|
||||
cachename, infilename, CRUNCH_VERSION);
|
||||
|
||||
for(p = progs; p != NULL; p = p->next) {
|
||||
fprintf(cachef, "\n");
|
||||
if(p->srcdir)
|
||||
fprintf(cachef, "special %s srcdir %s\n", p->name, p->srcdir);
|
||||
if(p->objdir)
|
||||
fprintf(cachef, "special %s objdir %s\n", p->name, p->objdir);
|
||||
if(p->objs) {
|
||||
fprintf(cachef, "special %s objs", p->name);
|
||||
output_strlst(cachef, p->objs);
|
||||
}
|
||||
fprintf(cachef, "special %s objpaths", p->name);
|
||||
output_strlst(cachef, p->objpaths);
|
||||
}
|
||||
fclose(cachef);
|
||||
}
|
||||
|
||||
|
||||
void gen_output_makefile(void)
|
||||
{
|
||||
prog_t *p;
|
||||
FILE *outmk;
|
||||
|
||||
sprintf(line, "generating %s", outmkname);
|
||||
status(line);
|
||||
|
||||
if((outmk = fopen(outmkname, "w")) == NULL) {
|
||||
perror(outmkname);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(outmk, "# %s - generated from %s by crunchgen %s\n\n",
|
||||
outmkname, infilename, CRUNCH_VERSION);
|
||||
|
||||
top_makefile_rules(outmk);
|
||||
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
prog_makefile_rules(outmk, p);
|
||||
|
||||
fprintf(outmk, "\n# ========\n");
|
||||
fclose(outmk);
|
||||
}
|
||||
|
||||
|
||||
void gen_output_cfile(void)
|
||||
{
|
||||
extern char *crunched_skel[];
|
||||
char **cp;
|
||||
FILE *outcf;
|
||||
prog_t *p;
|
||||
strlst_t *s;
|
||||
|
||||
sprintf(line, "generating %s", outcfname);
|
||||
status(line);
|
||||
|
||||
if((outcf = fopen(outcfname, "w")) == NULL) {
|
||||
perror(outcfname);
|
||||
goterror = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(outcf,
|
||||
"/* %s - generated from %s by crunchgen %s */\n",
|
||||
outcfname, infilename, CRUNCH_VERSION);
|
||||
|
||||
fprintf(outcf, "#define EXECNAME \"%s\"\n", execfname);
|
||||
for(cp = crunched_skel; *cp != NULL; cp++)
|
||||
fprintf(outcf, "%s\n", *cp);
|
||||
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
fprintf(outcf, "extern int _crunched_%s_stub();\n", p->ident);
|
||||
|
||||
fprintf(outcf, "\nstruct stub entry_points[] = {\n");
|
||||
for(p = progs; p != NULL; p = p->next) {
|
||||
fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
|
||||
p->name, p->ident);
|
||||
for(s = p->links; s != NULL; s = s->next)
|
||||
fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
|
||||
s->str, p->ident);
|
||||
}
|
||||
|
||||
fprintf(outcf, "\t{ EXECNAME, crunched_main },\n");
|
||||
fprintf(outcf, "\t{ NULL, NULL }\n};\n");
|
||||
fclose(outcf);
|
||||
}
|
||||
|
||||
|
||||
char *genident(char *str)
|
||||
{
|
||||
char *n,*s,*d;
|
||||
|
||||
/*
|
||||
* generates a Makefile/C identifier from a program name, mapping '-' to
|
||||
* '_' and ignoring all other non-identifier characters. This leads to
|
||||
* programs named "foo.bar" and "foobar" to map to the same identifier.
|
||||
*/
|
||||
|
||||
if((n = strdup(str)) == NULL)
|
||||
return NULL;
|
||||
for(d = s = n; *s != '\0'; s++) {
|
||||
if(*s == '-') *d++ = '_';
|
||||
else if(*s == '_' || isalnum(*s)) *d++ = *s;
|
||||
}
|
||||
*d = '\0';
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
char *dir_search(char *progname)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
strlst_t *dir;
|
||||
|
||||
for(dir=srcdirs; dir != NULL; dir=dir->next) {
|
||||
sprintf(path, "%s/%s", dir->str, progname);
|
||||
if(is_dir(path)) return dir->str;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void top_makefile_rules(FILE *outmk)
|
||||
{
|
||||
prog_t *p;
|
||||
|
||||
fprintf(outmk, "LIBS=");
|
||||
output_strlst(outmk, libs);
|
||||
|
||||
fprintf(outmk, "CRUNCHED_OBJS=");
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
fprintf(outmk, " %s.lo", p->name);
|
||||
fprintf(outmk, "\n");
|
||||
|
||||
fprintf(outmk, "SUBMAKE_TARGETS=");
|
||||
for(p = progs; p != NULL; p = p->next)
|
||||
fprintf(outmk, " %s_make", p->ident);
|
||||
fprintf(outmk, "\n\n");
|
||||
|
||||
fprintf(outmk, "%s: %s.o $(CRUNCHED_OBJS)\n",
|
||||
execfname, execfname);
|
||||
fprintf(outmk, "\t$(CC) -static -o %s %s.o $(CRUNCHED_OBJS) $(LIBS)\n",
|
||||
execfname, execfname);
|
||||
fprintf(outmk, "\tstrip %s\n", execfname);
|
||||
fprintf(outmk, "all: objs exe\nobjs: $(SUBMAKE_TARGETS)\n");
|
||||
fprintf(outmk, "exe: %s\n", execfname);
|
||||
fprintf(outmk, "clean:\n\trm -f %s *.lo *.o *_stub.c\n",
|
||||
execfname);
|
||||
}
|
||||
|
||||
|
||||
void prog_makefile_rules(FILE *outmk, prog_t *p)
|
||||
{
|
||||
fprintf(outmk, "\n# -------- %s\n\n", p->name);
|
||||
|
||||
if(p->srcdir && p->objs) {
|
||||
fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir);
|
||||
fprintf(outmk, "%s_OBJS=", p->ident);
|
||||
output_strlst(outmk, p->objs);
|
||||
fprintf(outmk, "%s_make:\n", p->ident);
|
||||
fprintf(outmk, "\t(cd $(%s_SRCDIR); make $(%s_OBJS))\n\n",
|
||||
p->ident, p->ident);
|
||||
}
|
||||
else
|
||||
fprintf(outmk, "%s_make:\n\t@echo \"** cannot make objs for %s\"\n\n",
|
||||
p->ident, p->name);
|
||||
|
||||
fprintf(outmk, "%s_OBJPATHS=", p->ident);
|
||||
output_strlst(outmk, p->objpaths);
|
||||
|
||||
fprintf(outmk, "%s_stub.c:\n", p->name);
|
||||
fprintf(outmk, "\techo \""
|
||||
"int _crunched_%s_stub(int argc, char **argv, char **envp)"
|
||||
"{return main(argc,argv,envp);}\" >%s_stub.c\n",
|
||||
p->ident, p->name);
|
||||
fprintf(outmk, "%s.lo: %s_stub.o $(%s_OBJPATHS)\n",
|
||||
p->name, p->name, p->ident);
|
||||
fprintf(outmk, "\tld -dc -r -o %s.lo %s_stub.o $(%s_OBJPATHS)\n",
|
||||
p->name, p->name, p->ident);
|
||||
fprintf(outmk, "\tcrunchide -k __crunched_%s_stub %s.lo\n",
|
||||
p->ident, p->name);
|
||||
}
|
||||
|
||||
void output_strlst(FILE *outf, strlst_t *lst)
|
||||
{
|
||||
for(; lst != NULL; lst = lst->next)
|
||||
fprintf(outf, " %s", lst->str);
|
||||
fprintf(outf, "\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================================
|
||||
* general library routines
|
||||
*
|
||||
*/
|
||||
|
||||
void status(char *str)
|
||||
{
|
||||
static int lastlen = 0;
|
||||
int len, spaces;
|
||||
|
||||
if(!verbose) return;
|
||||
|
||||
len = strlen(str);
|
||||
spaces = lastlen - len;
|
||||
if(spaces < 1) spaces = 1;
|
||||
|
||||
fprintf(stderr, " [%s]%*.*s\r", str, spaces, spaces, " ");
|
||||
fflush(stderr);
|
||||
lastlen = len;
|
||||
}
|
||||
|
||||
|
||||
void out_of_memory(void)
|
||||
{
|
||||
fprintf(stderr, "%s: %d: out of memory, stopping.\n", infilename, linenum);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void add_string(strlst_t **listp, char *str)
|
||||
{
|
||||
strlst_t *p1, *p2;
|
||||
|
||||
/* add to end, but be smart about dups */
|
||||
|
||||
for(p1 = NULL, p2 = *listp; p2 != NULL; p1 = p2, p2 = p2->next)
|
||||
if(!strcmp(p2->str, str)) return;
|
||||
|
||||
p2 = malloc(sizeof(strlst_t));
|
||||
if(p2) p2->str = strdup(str);
|
||||
if(!p2 || !p2->str)
|
||||
out_of_memory();
|
||||
|
||||
p2->next = NULL;
|
||||
if(p1 == NULL) *listp = p2;
|
||||
else p1->next = p2;
|
||||
}
|
||||
|
||||
|
||||
int is_dir(char *pathname)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if(stat(pathname, &buf) == -1)
|
||||
return 0;
|
||||
return S_ISDIR(buf.st_mode);
|
||||
}
|
||||
|
||||
int is_nonempty_file(char *pathname)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if(stat(pathname, &buf) == -1)
|
||||
return 0;
|
||||
|
||||
return S_ISREG(buf.st_mode) && buf.st_size > 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#! /bin/sh
|
||||
# idea and sed lines taken straight from flex
|
||||
|
||||
cat <<!EOF
|
||||
/* File created via mkskel.sh */
|
||||
|
||||
char *crunched_skel[] = {
|
||||
!EOF
|
||||
|
||||
sed 's/\\/&&/g' $* | sed 's/"/\\"/g' | sed 's/.*/ "&",/'
|
||||
|
||||
cat <<!EOF
|
||||
0
|
||||
};
|
||||
!EOF
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
PROG= crunchide
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,70 @@
|
|||
.\"
|
||||
.\" Copyright (c) 1994 University of Maryland
|
||||
.\" All Rights Reserved.
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, distribute, and sell this software and its
|
||||
.\" documentation for any purpose is hereby granted without fee, provided that
|
||||
.\" the above copyright notice appear in all copies and that both that
|
||||
.\" copyright notice and this permission notice appear in supporting
|
||||
.\" documentation, and that the name of U.M. not be used in advertising or
|
||||
.\" publicity pertaining to distribution of the software without specific,
|
||||
.\" written prior permission. U.M. makes no representations about the
|
||||
.\" suitability of this software for any purpose. It is provided "as is"
|
||||
.\" without express or implied warranty.
|
||||
.\"
|
||||
.\" U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
.\" BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
.\" IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.\" Author: James da Silva, Systems Design and Analysis Group
|
||||
.\" Computer Science Department
|
||||
.\" University of Maryland at College Park
|
||||
.\"
|
||||
.Dd June 14, 1994
|
||||
.Dt CRUNCHIDE 1
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm crunchide
|
||||
.Nd hides symbol names from ld, for crunching programs together
|
||||
.Sh SYNOPSIS
|
||||
.Nm crunchide
|
||||
.Op Fl f Ar keep-list-file
|
||||
.Op Fl k Ar keep-symbol
|
||||
.Op Ar object-file ...
|
||||
.Sh DESCRIPTION
|
||||
|
||||
.Nm Crunchide
|
||||
hides the global symbols of
|
||||
.Ar object-file
|
||||
such that they are ignored by subsequent runs of the linker,
|
||||
.Xr ld 1 .
|
||||
Some symbols may be left visible via the
|
||||
.Fl k Ar keep-symbol
|
||||
and
|
||||
.Fl f Ar keep-list-file
|
||||
options. The
|
||||
.Ar keep-list-file
|
||||
must contain a list of symbols to keep visible, one symbol per line.
|
||||
Note that the C compiler prepends an underscore in front of
|
||||
symbols, so to keep the C function ``foo'' visible, the option
|
||||
\&``-k _foo'' must be used.
|
||||
|
||||
.Pp
|
||||
.Nm Crunchide
|
||||
is designed as a companion program for
|
||||
.Xr crunchgen 1 ,
|
||||
which automates the process of creating crunched binaries from
|
||||
multiple component programs.
|
||||
.Sh SEE ALSO
|
||||
.Xr crunchgen 1 ,
|
||||
.Xr ld 1
|
||||
.Sh BUGS
|
||||
Should have just used symorder -t where available.
|
||||
.Sh AUTHOR
|
||||
.Nm Crunch
|
||||
was written by James da Silva <jds@cs.umd.edu>.
|
||||
.sp 0
|
||||
Copyright (c) 1994 University of Maryland. All Rights Reserved.
|
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
* Copyright (c) 1994 University of Maryland
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of U.M. not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. U.M. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: James da Silva, Systems Design and Analysis Group
|
||||
* Computer Science Department
|
||||
* University of Maryland at College Park
|
||||
*/
|
||||
/*
|
||||
* crunchide.c - tiptoes through an a.out symbol table, hiding all defined
|
||||
* global symbols. Allows the user to supply a "keep list" of symbols
|
||||
* that are not to be hidden. This program relies on the use of the
|
||||
* linker's -dc flag to actually put global bss data into the file's
|
||||
* bss segment (rather than leaving it as undefined "common" data).
|
||||
*
|
||||
* The point of all this is to allow multiple programs to be linked
|
||||
* together without getting multiple-defined errors.
|
||||
*
|
||||
* For example, consider a program "foo.c". It can be linked with a
|
||||
* small stub routine, called "foostub.c", eg:
|
||||
* int foo_main(int argc, char **argv){ return main(argc, argv); }
|
||||
* like so:
|
||||
* cc -c foo.c foostub.c
|
||||
* ld -dc -r foo.o foostub.o -o foo.combined.o
|
||||
* crunchide -k _foo_main foo.combined.o
|
||||
* at this point, foo.combined.o can be linked with another program
|
||||
* and invoked with "foo_main(argc, argv)". foo's main() and any
|
||||
* other globals are hidden and will not conflict with other symbols.
|
||||
*
|
||||
* TODO:
|
||||
* - resolve the theoretical hanging reloc problem (see check_reloc()
|
||||
* below). I have yet to see this problem actually occur in any real
|
||||
* program. In what cases will gcc/gas generate code that needs a
|
||||
* relative reloc from a global symbol, other than PIC? The
|
||||
* solution is to not hide the symbol from the linker in this case,
|
||||
* but to generate some random name for it so that it doesn't link
|
||||
* with anything but holds the place for the reloc.
|
||||
* - arrange that all the BSS segments start at the same address, so
|
||||
* that the final crunched binary BSS size is the max of all the
|
||||
* component programs' BSS sizes, rather than their sum.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <a.out.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
char *pname = "crunchide";
|
||||
|
||||
void usage(void);
|
||||
|
||||
void add_to_keep_list(char *symbol);
|
||||
void add_file_to_keep_list(char *filename);
|
||||
|
||||
void hide_syms(char *filename);
|
||||
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int ch;
|
||||
|
||||
if(argc > 0) pname = argv[0];
|
||||
|
||||
while ((ch = getopt(argc, argv, "k:f:")) != EOF)
|
||||
switch(ch) {
|
||||
case 'k':
|
||||
add_to_keep_list(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
add_file_to_keep_list(optarg);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if(argc == 0) usage();
|
||||
|
||||
while(argc) {
|
||||
hide_syms(*argv);
|
||||
argc--, argv++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-k <symbol-name>] [-f <keep-list-file>] <files> ...\n",
|
||||
pname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* ---------------------------- */
|
||||
|
||||
struct keep {
|
||||
struct keep *next;
|
||||
char *sym;
|
||||
} *keep_list;
|
||||
|
||||
void add_to_keep_list(char *symbol)
|
||||
{
|
||||
struct keep *newp, *prevp, *curp;
|
||||
int cmp;
|
||||
|
||||
for(curp = keep_list, prevp = NULL; curp; prevp = curp, curp = curp->next)
|
||||
if((cmp = strcmp(symbol, curp->sym)) <= 0) break;
|
||||
|
||||
if(curp && cmp == 0)
|
||||
return; /* already in table */
|
||||
|
||||
newp = (struct keep *) malloc(sizeof(struct keep));
|
||||
if(newp) newp->sym = strdup(symbol);
|
||||
if(newp == NULL || newp->sym == NULL) {
|
||||
fprintf(stderr, "%s: out of memory for keep list\n", pname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
newp->next = curp;
|
||||
if(prevp) prevp->next = newp;
|
||||
else keep_list = newp;
|
||||
}
|
||||
|
||||
int in_keep_list(char *symbol)
|
||||
{
|
||||
struct keep *curp;
|
||||
int cmp;
|
||||
|
||||
for(curp = keep_list; curp; curp = curp->next)
|
||||
if((cmp = strcmp(symbol, curp->sym)) <= 0) break;
|
||||
|
||||
return curp && cmp == 0;
|
||||
}
|
||||
|
||||
void add_file_to_keep_list(char *filename)
|
||||
{
|
||||
FILE *keepf;
|
||||
char symbol[1024];
|
||||
int len;
|
||||
|
||||
if((keepf = fopen(filename, "r")) == NULL) {
|
||||
perror(filename);
|
||||
usage();
|
||||
}
|
||||
|
||||
while(fgets(symbol, 1024, keepf)) {
|
||||
len = strlen(symbol);
|
||||
if(len && symbol[len-1] == '\n')
|
||||
symbol[len-1] = '\0';
|
||||
|
||||
add_to_keep_list(symbol);
|
||||
}
|
||||
fclose(keepf);
|
||||
}
|
||||
|
||||
/* ---------------------- */
|
||||
|
||||
int nsyms, ntextrel, ndatarel;
|
||||
struct exec *hdrp;
|
||||
char *aoutdata, *strbase;
|
||||
struct relocation_info *textrel, *datarel;
|
||||
struct nlist *symbase;
|
||||
|
||||
|
||||
#define SYMSTR(sp) &strbase[(sp)->n_un.n_strx]
|
||||
|
||||
/* is the symbol a global symbol defined in the current file? */
|
||||
#define IS_GLOBAL_DEFINED(sp) \
|
||||
(((sp)->n_type & N_EXT) && ((sp)->n_type & N_TYPE) != N_UNDF)
|
||||
|
||||
/* is the relocation entry dependent on a symbol? */
|
||||
#define IS_SYMBOL_RELOC(rp) \
|
||||
((rp)->r_extern||(rp)->r_baserel||(rp)->r_jmptable)
|
||||
|
||||
void check_reloc(char *filename, struct relocation_info *relp);
|
||||
|
||||
void hide_syms(char *filename)
|
||||
{
|
||||
int inf, outf, rc;
|
||||
struct stat infstat;
|
||||
struct relocation_info *relp;
|
||||
struct nlist *symp;
|
||||
|
||||
/*
|
||||
* Open the file and do some error checking.
|
||||
*/
|
||||
|
||||
if((inf = open(filename, O_RDWR)) == -1) {
|
||||
perror(filename);
|
||||
return;
|
||||
}
|
||||
|
||||
if(fstat(inf, &infstat) == -1) {
|
||||
perror(filename);
|
||||
close(inf);
|
||||
return;
|
||||
}
|
||||
|
||||
if(infstat.st_size < sizeof(struct exec)) {
|
||||
fprintf(stderr, "%s: short file\n", filename);
|
||||
close(inf);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the entire file into memory. XXX - Really, we only need to
|
||||
* read the header and from TRELOFF to the end of the file.
|
||||
*/
|
||||
|
||||
if((aoutdata = (char *) malloc(infstat.st_size)) == NULL) {
|
||||
fprintf(stderr, "%s: too big to read into memory\n", filename);
|
||||
close(inf);
|
||||
return;
|
||||
}
|
||||
|
||||
if((rc = read(inf, aoutdata, infstat.st_size)) < infstat.st_size) {
|
||||
fprintf(stderr, "%s: read error: %s\n", filename,
|
||||
rc == -1? strerror(errno) : "short read");
|
||||
close(inf);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the header and calculate offsets and sizes from it.
|
||||
*/
|
||||
|
||||
hdrp = (struct exec *) aoutdata;
|
||||
|
||||
if(N_BADMAG(*hdrp)) {
|
||||
fprintf(stderr, "%s: bad magic: not an a.out file\n", filename);
|
||||
close(inf);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
textrel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp));
|
||||
datarel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp) +
|
||||
hdrp->a_trsize);
|
||||
#else
|
||||
textrel = (struct relocation_info *) (aoutdata + N_TRELOFF(*hdrp));
|
||||
datarel = (struct relocation_info *) (aoutdata + N_DRELOFF(*hdrp));
|
||||
#endif
|
||||
symbase = (struct nlist *) (aoutdata + N_SYMOFF(*hdrp));
|
||||
strbase = (char *) (aoutdata + N_STROFF(*hdrp));
|
||||
|
||||
ntextrel = hdrp->a_trsize / sizeof(struct relocation_info);
|
||||
ndatarel = hdrp->a_drsize / sizeof(struct relocation_info);
|
||||
nsyms = hdrp->a_syms / sizeof(struct nlist);
|
||||
|
||||
/*
|
||||
* Zap the type field of all globally-defined symbols. The linker will
|
||||
* subsequently ignore these entries. Don't zap any symbols in the
|
||||
* keep list.
|
||||
*/
|
||||
|
||||
for(symp = symbase; symp < symbase + nsyms; symp++)
|
||||
if(IS_GLOBAL_DEFINED(symp) && !in_keep_list(SYMSTR(symp)))
|
||||
symp->n_type = 0;
|
||||
|
||||
/*
|
||||
* Check whether the relocation entries reference any symbols that we
|
||||
* just zapped. I don't know whether ld can handle this case, but I
|
||||
* haven't encountered it yet. These checks are here so that the program
|
||||
* doesn't fail silently should such symbols be encountered.
|
||||
*/
|
||||
|
||||
for(relp = textrel; relp < textrel + ntextrel; relp++)
|
||||
check_reloc(filename, relp);
|
||||
for(relp = datarel; relp < datarel + ndatarel; relp++)
|
||||
check_reloc(filename, relp);
|
||||
|
||||
/*
|
||||
* Write the .o file back out to disk. XXX - Really, we only need to
|
||||
* write the symbol table entries back out.
|
||||
*/
|
||||
lseek(inf, 0, SEEK_SET);
|
||||
if((rc = write(inf, aoutdata, infstat.st_size)) < infstat.st_size) {
|
||||
fprintf(stderr, "%s: write error: %s\n", filename,
|
||||
rc == -1? strerror(errno) : "short write");
|
||||
}
|
||||
|
||||
close(inf);
|
||||
}
|
||||
|
||||
|
||||
void check_reloc(char *filename, struct relocation_info *relp)
|
||||
{
|
||||
/* bail out if we zapped a symbol that is needed */
|
||||
if(IS_SYMBOL_RELOC(relp) && symbase[relp->r_symbolnum].n_type == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: oops, have hanging relocation for %s: bailing out!\n",
|
||||
filename, SYMSTR(&symbase[relp->r_symbolnum]));
|
||||
exit(1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
CRUNCHED= fixit
|
||||
|
||||
# below is boiler-plate to make $(CRUNCHED) from $(CRUNCHED).conf
|
||||
# I'd use PROG instead of CRUNCHED, but the system makefiles REALLY want
|
||||
# to build things in the normal way if you use PROG.
|
||||
|
||||
CONF= $(CRUNCHED).conf
|
||||
|
||||
OUTMK= $(CRUNCHED).mk
|
||||
OUTPUTS= $(OUTMK) $(CRUNCHED).c $(CRUNCHED).cache
|
||||
|
||||
NOMAN=
|
||||
CLEANFILES+=$(CRUNCHED) $(OUTPUTS) *.o *.lo *_stub.c
|
||||
|
||||
all: $(CRUNCHED)
|
||||
exe: $(CRUNCHED)
|
||||
|
||||
$(OUTPUTS): $(CONF)
|
||||
crunchgen ${.CURDIR}/$(CONF)
|
||||
|
||||
$(CRUNCHED): $(OUTPUTS) submake
|
||||
|
||||
submake:
|
||||
make -f $(OUTMK)
|
||||
objs:
|
||||
make -f $(OUTMK) objs
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,44 @@
|
|||
# fixit.conf - put in anything we think we might want on a fixit floppy
|
||||
|
||||
# first, we list the source dirs that our programs reside in. These are
|
||||
# searched in order listed to find the dir containing each program.
|
||||
|
||||
srcdirs /usr/src/bin /usr/src/sbin /usr/src/usr.bin /usr/src/usr.sbin
|
||||
srcdirs /usr/src/gnu/usr.bin
|
||||
|
||||
# second, we list all the programs we want to include in our crunched binary.
|
||||
# The order doesn't matter. Any program that needs hard links to it gets an
|
||||
# `ln' directive.
|
||||
|
||||
# /bin stuff
|
||||
|
||||
progs cat chmod cp date dd df echo ed expr hostname kill ln ls mkdir
|
||||
progs mt mv pwd rcp rm rmdir sh sleep stty sync test
|
||||
|
||||
ln test [
|
||||
ln sh -sh # init invokes the shell this way
|
||||
ln sh -
|
||||
|
||||
# /sbin stuff
|
||||
|
||||
progs badsect chown clri disklabel dump dmesg fdisk fsck halt ifconfig init
|
||||
progs mknod mount newfs ping reboot restore swapon umount
|
||||
ln dump rdump
|
||||
ln restore rrestore
|
||||
|
||||
# /usr/bin stuff
|
||||
|
||||
progs ftp rsh sed telnet rlogin vi
|
||||
|
||||
# gnu stuff
|
||||
|
||||
progs cpio gzip
|
||||
ln gzip gunzip
|
||||
ln gzip gzcat
|
||||
|
||||
# finally, we specify the libraries to link in with our binary
|
||||
|
||||
libs -ledit # NetBSDism
|
||||
libs -lcrypt # but don't include this when exporting :-(
|
||||
libs -lcurses -ltermcap
|
||||
libs -lkvm -ltelnet -lutil -ll
|
|
@ -0,0 +1,26 @@
|
|||
# $Id: freebsd-filesystem.conf,v 1.1.1.1 1994/08/29 14:47:30 cgd Exp $
|
||||
|
||||
srcdirs /usr/src/bin /usr/src/sbin /usr/src/gnu/usr.bin /usr/src/usr.sbin
|
||||
|
||||
# /bin
|
||||
progs sh expr ls mkdir rm sync test
|
||||
ln test [
|
||||
|
||||
# These are needed because of UN*X's idiotic way of indicating that something
|
||||
# is a login shell.
|
||||
ln sh -
|
||||
ln sh -sh
|
||||
|
||||
# /sbin
|
||||
progs disklabel fdisk halt init mount mount_pcfs newfs umount
|
||||
|
||||
# /usr/bin
|
||||
progs cpio gzip
|
||||
ln gzip gunzip
|
||||
ln gzip gzcat
|
||||
ln gzip zcat
|
||||
|
||||
# /usr/sbin
|
||||
progs bad144
|
||||
|
||||
libs -lutil
|
|
@ -0,0 +1,18 @@
|
|||
# $Id: freebsd-kcopy.conf,v 1.1.1.1 1994/08/29 14:47:30 cgd Exp $
|
||||
|
||||
srcdirs /usr/src/bin /usr/src/sbin
|
||||
|
||||
# Programs from bin/
|
||||
progs sh cp echo test
|
||||
ln test [
|
||||
|
||||
# These are needed because of UN*X's idiotic way of indicating that something
|
||||
# is a login shell.
|
||||
ln sh -
|
||||
ln sh -sh
|
||||
|
||||
#
|
||||
# Programs from sbin/
|
||||
progs mount mount_isofs mount_pcfs fsck halt init umount
|
||||
|
||||
libs -lutil
|
|
@ -0,0 +1,146 @@
|
|||
# really-big.conf - just about everything, just for testing.
|
||||
# This ends up having some good examples of the use of specials for
|
||||
# those hard-to-reach programs. I stopped when I got tired, but we
|
||||
# could probably get even more stuff (like libexec stuff) in here.
|
||||
#
|
||||
# This produces a 4608000 byte binary. Pretty sick and twisted, eh?
|
||||
|
||||
# =========================================================================
|
||||
|
||||
srcdirs /usr/src/bin
|
||||
|
||||
progs cat chmod cp csh date dd df domainname echo ed expr hostname kill
|
||||
progs ln ls mkdir mt mv ps pwd rcp rm rmail rmdir sh sleep stty sync test
|
||||
|
||||
ln test [
|
||||
ln sh -sh
|
||||
|
||||
|
||||
# =========================================================================
|
||||
|
||||
srcdirs /usr/src/sbin
|
||||
|
||||
progs badsect bim clri disklabel dmesg dump dumpfs fdisk fsck halt
|
||||
progs ifconfig init mknod modload modunload mount mount_fdesc mount_isofs
|
||||
progs mount_kernfs mount_lofs mount_msdos mount_portal mount_procfs mountd
|
||||
progs newfs nfsd nfsiod ping quotacheck reboot restore route routed savecore
|
||||
progs shutdown slattach swapon ttyflags tunefs umount
|
||||
# shell scripts: fastboot
|
||||
|
||||
ln dump rdump
|
||||
ln restore rrestore
|
||||
|
||||
|
||||
# =========================================================================
|
||||
|
||||
srcdirs /usr/src/usr.bin
|
||||
|
||||
progs apropos ar asa at basename biff cal calendar cap_mkdb checknr chpass
|
||||
progs cksum cmp col colcrt colrm column comm compress crontab ctags cut
|
||||
progs dirname du env error expand false file find finger fmt fold fpr from
|
||||
progs fsplit fstat ftp getconf getopt gprof head hexdump id indent ipcrm
|
||||
progs ipcs join kdump ktrace last lastcomm leave lex lock logger locate
|
||||
progs login logname look m4 machine mail make man mesg mkfifo
|
||||
progs mkstr modstat more msgs netstat newsyslog nfsstat nice nm nohup
|
||||
progs pagesize passwd paste patch pr printenv printf quota ranlib
|
||||
progs renice rev rlogin rpcgen rpcinfo rsh rup ruptime rusers rwall rwho
|
||||
progs script sed showmount size soelim split strings strip su tail talk
|
||||
progs tcopy tee telnet tftp time tip tn3270 touch tput tr true tset tsort
|
||||
progs tty ul uname unexpand unifdef uniq units unvis users uudecode uuencode
|
||||
progs vacation vgrind vi vis vmstat w wall wc what whatis whereis who
|
||||
progs whois window write xargs xinstall xstr yacc yes ypcat ypmatch ypwhich
|
||||
|
||||
# shell scripts: lorder mkdep shar which
|
||||
# problems: rdist uses libcompat.a(regex.o), which conflicts with
|
||||
# libedit(readline.o) over regerror().
|
||||
|
||||
# special requirements
|
||||
|
||||
special locate srcdir /usr/src/usr.bin/locate/locate
|
||||
special tn3270 srcdir /usr/src/usr.bin/tn3270/tn3270
|
||||
|
||||
|
||||
# =========================================================================
|
||||
|
||||
srcdirs /usr/src/usr.sbin
|
||||
|
||||
progs ac accton amd arp bad144 catman chown chroot config config.new cron
|
||||
progs dev_mkdb diskpart edquota flcopy gettable grfinfo hilinfo htable inetd
|
||||
progs iostat iteconfig kvm_mkdb mrouted mtree named portmap pppd
|
||||
progs pstat pwd_mkdb quot quotaon rarpd rbootd repquota rmt rpc.bootparamd
|
||||
progs rwhod sa sliplogin slstats spray sysctl syslogd tcpdump
|
||||
progs traceroute trpt trsp update vipw vnconfig ypbind yppoll ypset
|
||||
|
||||
special amd srcdir /usr/src/usr.sbin/amd/amd
|
||||
special amd objs vers.amd.o afs_ops.o am_ops.o clock.o util.o xutil.o efs_ops.o mapc.o info_file.o info_hes.o info_ndbm.o info_passwd.o info_nis.o info_union.o map.o srvr_afs.o srvr_nfs.o mntfs.o misc_rpc.o mount_fs.o mtab.o mtab_bsd.o nfs_ops.o nfs_prot_svc.o nfs_start.o nfs_subr.o opts.o pfs_ops.o rpc_fwd.o sched.o sfs_ops.o amq_svc.o amq_subr.o umount_fs.o host_ops.o nfsx_ops.o ufs_ops.o ifs_ops.o amd.o get_args.o restart.o wire.o
|
||||
|
||||
|
||||
srcdirs /usr/src/usr.sbin/lpr # lpr subsystem
|
||||
progs lpr lpc lpq lprm pac lptest
|
||||
special lpr srcdir /usr/src/usr.sbin/lpr/lpr
|
||||
|
||||
srcdirs /usr/src/usr.sbin/sendmail # sendmail subsystem
|
||||
progs mailstats makemap praliases sendmail
|
||||
special sendmail srcdir /usr/src/usr.sbin/sendmail/src
|
||||
ln sendmail newaliases
|
||||
ln sendmail mailq
|
||||
|
||||
srcdirs /usr/src/usr.sbin/timed # timed & timedc
|
||||
progs timed timedc
|
||||
special timed srcdir /usr/src/usr.sbin/timed/timed
|
||||
|
||||
srcdirs /usr/src/usr.sbin/yp # yp subsystem
|
||||
progs ypbind ypwhich ypcat ypmatch ypset yppoll
|
||||
|
||||
|
||||
# =========================================================================
|
||||
|
||||
srcdirs /usr/src/gnu/usr.bin
|
||||
|
||||
progs bc cpio diff diff3 gas gawk grep gzip sdiff sort tar
|
||||
# shell scripts: send-pr
|
||||
|
||||
srcdirs /usr/src/gnu/usr.bin/ld # ldd and ldconfig
|
||||
progs ld ldd ldconfig
|
||||
|
||||
# rcs stuff loses because there are cross dependencies between librcs.a and
|
||||
# the individual programs. The solution would be to specify the objpaths
|
||||
# directly for each one, and include the full path to librcs.a each the
|
||||
# objpaths.
|
||||
|
||||
# srcdirs /usr/src/gnu/usr.bin/rcs # rcs subsystem
|
||||
# progs ci co ident merge rcs rcsclean rcsdiff rcsmerge rlog
|
||||
# # shell script: rcsfreeze
|
||||
# special rcs srcdir /usr/src/gnu/usr.bin/rcs/rcs
|
||||
# libs /usr/src/gnu/usr.bin/rcs/lib/obj/librcs.a
|
||||
|
||||
# gdb loses too
|
||||
# progs gdb
|
||||
# special gdb srcdir /usr/src/gnu/usr.bin/gdb/gdb
|
||||
# libs /usr/src/gnu/usr.bin/gdb/bfd/obj/libbfd.a
|
||||
# libs /usr/src/gnu/usr.bin/gdb/readline/obj/libreadline.a
|
||||
# libs /usr/src/gnu/usr.bin/gdb/libiberty/obj/libiberty.a
|
||||
|
||||
# groff has the same problem as rcs
|
||||
# srcdirs /usr/src/gnu/usr.bin/groff # groff subsystem
|
||||
# progs groff troff tbl pic eqn grops grotty grodvi refer lookbib
|
||||
# progs indxbib lkbib tfmtodit addftinfo pfbtops psbb
|
||||
# shell script: nroff
|
||||
# special groff srcdir /usr/src/gnu/usr.bin/groff/groff
|
||||
# libs /usr/src/gnu/usr.bin/groff/libgroff/obj/libgroff.a
|
||||
# libs /usr/src/gnu/usr.bin/groff/libbib/obj/libbib.a
|
||||
# libs /usr/src/gnu/usr.bin/groff/libdriver/obj/libdriver.a
|
||||
|
||||
srcdirs /usr/src/gnu/usr.bin/gcc2 # gcc & friends
|
||||
progs cc cpp cc1
|
||||
|
||||
# cc1 has the same problem as rcs and groff, but since there's only one program
|
||||
# I'll go ahead and solve it as an example.
|
||||
|
||||
special cc1 objpaths /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-parse.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-lang.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-lex.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-pragma.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-decl.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-typeck.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-convert.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-aux-info.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-iterate.o /usr/src/gnu/usr.bin/gcc2/common/obj/libcc1.a
|
||||
|
||||
ln gzip gunzip
|
||||
ln gzip gzcat
|
||||
|
||||
libs -ledit -lgnumalloc -lc -lcrypt -ltermcap -lcurses -ltelnet -lutil -lkvm
|
||||
libs -ll -ly -lm -lresolv -lrpcsvc -lcompat
|
Loading…
Reference in New Issue