Subject: toolchain/19016: BFD'fied crunchide(1) patch to build crunched binary on MIPS ports
To: None <gnats-bugs@gnats.netbsd.org>
From: None <tsutsui@ceres.dti.ne.jp>
List: netbsd-bugs
Date: 11/12/2002 00:15:08
>Number:         19016
>Category:       toolchain
>Synopsis:       BFD'fied crunchide(1) patch to build crunched binary on MIPS ports
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    toolchain-manager
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Mon Nov 11 07:16:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Izumi Tsutsui
>Release:        NetBSD 1.6K around 20021110
>Organization:
>Environment:
System: NetBSD/arc 1.6K 
Architecture: mipsel
Machine: arc (R4400 Express5800/230)
>Description:
Old crunchide(1) was used to hide global symbols before linking
all objects to be crunched, and it renames all symbols in the files.
Newer crunchgen(1) is changed to use objcopy(1) to hide global symbols
with different way. It does not rename them, but it makes all symbols
local to the file. But on mips ports, local symbols are handled
different way on linking, so changing all global symbols to local
ones causes the problem.

According to comments in crunchide/exec_elf32.c:
 * This function 'hides' (some of) ELF executable file's symbols.
 * It hides them by renaming them to "_$$hide$$ <filename> <symbolname>".
 * Symbols in the global keep list, or which are marked as being undefined,
 * are left alone.
 *
 * An old version of this code shuffled various tables around, turning
 * global symbols to be hidden into local symbols.  That lost on the
 * mips, because CALL16 relocs must reference global symbols, and, if
 * those symbols were being hidden, they were no longer global.

>How-To-Repeat:
Current pmax miniroot and rescue build for mips are broken.

>Fix:
BFD'fied crunchide patch is attached. This patch is based on
pkgsrc/cross/bfd-crunchide, written by Kazuki Sakamoto.

The only possible problem is GPL requirements of libbfd, but I guess
copyright notice in crunchide.c can be accepted by GPL.

---
Index: distrib/sets/makeflist
===================================================================
RCS file: /cvsroot/basesrc/distrib/sets/makeflist,v
retrieving revision 1.54
diff -u -r1.54 makeflist
--- distrib/sets/makeflist	2002/10/10 20:46:39	1.54
+++ distrib/sets/makeflist	2002/11/11 14:17:34
@@ -146,11 +146,6 @@
 		fi
 	fi
 
-	# XXX MIPS does not support rescue right now.
-	if [ ${machine_cpu} = "mips" ]; then
-		continue
-	fi
-
 	if [ -f $setd/lists/$setname/rescue.mi ]; then
 		cat $setd/lists/$setname/rescue.mi
 	fi
Index: rescue/Makefile
===================================================================
RCS file: /cvsroot/basesrc/rescue/Makefile,v
retrieving revision 1.6
diff -u -r1.6 Makefile
--- rescue/Makefile	2002/10/17 01:49:18	1.6
+++ rescue/Makefile	2002/11/11 14:19:09
@@ -30,20 +30,9 @@
 
 .include "${DISTRIBDIR}/common/Makefile.crunch"
 
-# XXX Make sure to update distrib/sets/makeflist when this conditional
-# XXX is changed or removed.
-.if ${MACHINE_CPU} == "mips"						# {
-
-realall install:
-	@echo "WARNING: src/rescue not built on ${MACHINE_ARCH} due to broken crunchgen"
-
-.else									# } {
-
 realall: ${CRUNCHBIN}
 
 install: ${CRUNCHBIN}
 	${PARSELIST} -v mode=install ${LISTS} | ${MAKE} -f - install
-
-.endif									# }
 
 .include <bsd.prog.mk>
Index: share/mk/bsd.own.mk
===================================================================
RCS file: /cvsroot/sharesrc/share/mk/bsd.own.mk,v
retrieving revision 1.316
diff -u -r1.316 bsd.own.mk
--- share/mk/bsd.own.mk	2002/10/22 18:48:29	1.316
+++ share/mk/bsd.own.mk	2002/11/11 14:19:25
@@ -136,6 +136,7 @@
 COMPILE_ET=	${TOOLDIR}/bin/nbcompile_et
 CONFIG=		${TOOLDIR}/bin/nbconfig
 CRUNCHGEN=	MAKE=${.MAKE:Q} ${TOOLDIR}/bin/nbcrunchgen
+CRUNCHIDE=	${TOOLDIR}/bin/${MACHINE_GNU_PLATFORM}-crunchide
 CTAGS=		${TOOLDIR}/bin/nbctags
 DBSYM=		${TOOLDIR}/bin/${MACHINE_GNU_PLATFORM}-dbsym
 ELF2ECOFF=	${TOOLDIR}/bin/nbmips-elf2ecoff
Index: tools/Makefile
===================================================================
RCS file: /cvsroot/basesrc/tools/Makefile,v
retrieving revision 1.60
diff -u -r1.60 Makefile
--- tools/Makefile	2002/09/19 17:13:01	1.60
+++ tools/Makefile	2002/11/11 14:20:33
@@ -3,7 +3,7 @@
 .include <bsd.own.mk>
 
 .if ${TOOLCHAIN_MISSING} != "yes"
-TOOLCHAIN_BITS= toolchain .WAIT dbsym mdsetimage
+TOOLCHAIN_BITS= toolchain .WAIT crunchide dbsym mdsetimage
 # XXX Eventually, we want to be able to build dbsym and mdsetimage
 # XXX if EXTERNAL_TOOLCHAIN is set.
 .endif
Index: usr.bin/crunch/crunchgen/crunchgen.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/crunch/crunchgen/crunchgen.c,v
retrieving revision 1.40
diff -u -r1.40 crunchgen.c
--- usr.bin/crunch/crunchgen/crunchgen.c	2002/08/20 01:52:58	1.40
+++ usr.bin/crunch/crunchgen/crunchgen.c	2002/11/11 14:20:40
@@ -827,11 +827,7 @@
     fprintf(outmk, "DBG=%s\n", dbg);
     fprintf(outmk, "STRIP?=strip\n");
     fprintf(outmk, "MAKE?=make\n");
-#ifdef NEW_TOOLCHAIN
-    fprintf(outmk, "OBJCOPY?=objcopy\n");
-#else
     fprintf(outmk, "CRUNCHIDE?=crunchide\n");
-#endif
 
     fprintf(outmk, "CRUNCHED_OBJS=");
     for(p = progs; p != NULL; p = p->next)
@@ -902,16 +898,9 @@
 		p->name, p->name, p->ident);
     fprintf(outmk, "\t${LD} -dc -r -o %s.cro %s_stub.o $(%s_OBJPATHS)\n", 
 	    p->name, p->name, p->ident);
-#ifdef NEW_TOOLCHAIN
-    fprintf(outmk, "\t${OBJCOPY} --keep-global-symbol _crunched_%s_stub ",
-  	    p->ident);
-    for (lst = p->keepsymbols; lst != NULL; lst = lst->next)
-	fprintf(outmk, "--keep-global-symbol %s ", lst->str);
-#else
     fprintf(outmk, "\t${CRUNCHIDE} -k _crunched_%s_stub ", p->ident);
     for (lst = p->keepsymbols; lst != NULL; lst = lst->next)
 	fprintf(outmk, "-k %s ", lst->str);
-#endif
     fprintf(outmk, "%s.cro\n", p->name);
 }
 
--- /dev/null	Mon Nov 11 20:54:40 2002
+++ gnu/usr.bin/crunchide/Makefile	Mon Nov 11 02:03:36 2002
@@ -0,0 +1,36 @@
+#	$NetBSD$
+
+.include <bsd.own.mk>
+
+.if (defined(HOSTPROG) && \
+     (${TOOLCHAIN_MISSING} != "yes" || defined(EXTERNAL_TOOLCHAIN))) || \
+    ${MKBFD} != "no"
+TOP=		${NETBSDSRCDIR}/gnu
+DIST=		${TOP}/dist/toolchain
+
+PROG=		crunchide
+MAN=		crunchide.1
+
+CPPFLAGS+=	-I${BFDDIR} -I${DIST}/bfd -I${DIST}/binutils -I${DIST}/include
+
+DPADD+=		${BFDDIR}/libbfd.a
+LDADD+=		-L${BFDDIR} -lbfd
+
+DPADD+=		${IBERTYDIR}/libiberty.a
+LDADD+=		-L${IBERTYDIR} -liberty
+
+.ifndef HOSTPROG
+.include	"${TOP}/lib/libbfd/arch/${MACHINE_ARCH}/defs.mk"
+
+BFDDIR!=	cd ${TOP}/lib/libbfd && ${PRINTOBJDIR}
+IBERTYDIR!=	cd ${TOP}/lib/libiberty && ${PRINTOBJDIR}
+
+CPPFLAGS+=	-I${TOP}/lib/libbfd/arch/${MACHINE_ARCH} ${G_INCLUDES}
+LDADD+=		-lintl
+DPADD+=		${LIBINTL}
+.endif # HOSTPROG
+.endif # MKBFD != no
+
+.ifndef HOSTPROG
+.include <bsd.prog.mk>
+.endif # HOSTPROG
--- /dev/null	Mon Nov 11 20:54:40 2002
+++ gnu/usr.bin/crunchide/crunchide.1	Mon Nov 11 02:03:36 2002
@@ -0,0 +1,94 @@
+.\"	$NetBSD$
+.\"
+.\" 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
+.Sh NAME
+.Nm crunchide
+.Nd hides symbol names from ld, for crunching programs together
+.Sh SYNOPSIS
+.Nm ""
+.Bk -words
+.Op Fl b Ar bfdname
+.Ek
+.Bk -words
+.Op Fl f Ar keep-list-file
+.Ek
+.Bk -words
+.Op Fl k Ar keep-symbol
+.Ek
+.Bk -words
+.Op Ar object-file ...
+.Ek
+.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.
+The names given by
+.Ar keep-symbol
+or in
+.Ar keep-list-file
+should be C names.  For example,
+to keep the C function
+.Dq foo
+visible, the option
+.Dq -k foo
+should be used.
+.Pp
+To recognize kernel executable format, the
+.Fl b
+flag specifies BFD name of kernel.
+.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 AUTHORS
+.Nm Crunch
+was written by James da Silva <jds@cs.umd.edu>.
+.sp 0
+Copyright (c) 1994 University of Maryland.  All Rights Reserved.
+.Pp
+Chris Demetriou <cgd@netbsd.org> reorganized
+.Nm
+so that it supported multiple object formats, and added
+ELF object support and ECOFF object recognition.
+.sp 0
+Copyright (c) 1997 Christopher G. Demetriou.  All Rights Reserved.
--- /dev/null	Mon Nov 11 20:54:40 2002
+++ gnu/usr.bin/crunchide/crunchide.c	Mon Nov 11 02:07:19 2002
@@ -0,0 +1,447 @@
+/* $NetBSD$ */
+/* NetBSD: crunchide.c,v 1.9 1999/01/11 22:40:00 kleink Exp 	 */
+
+/*
+ * Copyright (c) 1997 Christopher G. Demetriou.  All rights reserved.
+ * 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 <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: crunchide.c,v 1.2 2001/03/23 13:36:18 wiz Exp $");
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <a.out.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <bfd.h>
+
+extern const char *__progname;
+
+void usage      __P((void));
+void add_to_keep_list __P((char *));
+void add_file_to_keep_list __P((char *));
+int hide_syms   __P((const char *, char *));
+static void setup_section __P((bfd *, sec_ptr, PTR));
+static void copy_section __P((bfd *, sec_ptr, PTR));
+
+int verbose;
+
+struct keep {
+	struct keep *next;
+	char *sym;
+} *keep_list;
+
+struct bfd_cookie {
+	bfd *bfd;
+	asymbol **symtable;
+};
+
+int
+main(argc, argv)
+	int argc;
+	char **argv;
+{
+	int ch, errors;
+	char *bfdname = NULL;
+
+	while ((ch = getopt(argc, argv, "b:k:f:v")) != -1)
+		switch (ch) {
+		case 'b':
+			bfdname = optarg;
+			break;
+		case 'k':
+			add_to_keep_list(optarg);
+			break;
+		case 'f':
+			add_file_to_keep_list(optarg);
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		default:
+			usage();
+		}
+
+	argc -= optind;
+	argv += optind;
+
+	if (argc == 0)
+		usage();
+
+	errors = 0;
+	while (argc) {
+		if (hide_syms(*argv, bfdname))
+			errors = 1;
+		argc--, argv++;
+	}
+
+	return errors;
+}
+
+void 
+usage()
+{
+	const char **list;
+
+	fprintf(stderr,
+"Usage: %s [-b bfdname] [-k <symbol-name>] [-f <keep-list-file>] <files> ...\n",
+		__progname);
+	fprintf(stderr, "supported targets:");
+	for (list = bfd_target_list(); *list != NULL; list++)
+		fprintf(stderr, " %s", *list);
+	fprintf(stderr, "\n");
+	exit(1);
+}
+
+void 
+add_to_keep_list(symbol)
+	char *symbol;
+{
+	struct keep *newp, *prevp, *curp;
+	int cmp;
+
+	cmp = 0;
+
+	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", __progname);
+		exit(1);
+	}
+	newp->next = curp;
+	if (prevp)
+		prevp->next = newp;
+	else
+		keep_list = newp;
+}
+
+int 
+in_keep_list(symbol)
+	const char *symbol;
+{
+	struct keep *curp;
+	int cmp;
+
+	cmp = 0;
+
+	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(filename)
+	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 
+hide_syms(filename, bfdname)
+	const char *filename;
+	char *bfdname;
+{
+	int i, n, rv = 0;
+	bfd *org_bfd = NULL, *new_bfd = NULL;
+	char tempname[16];
+	char **name;
+	long storage_needed, number_of_symbols;
+	size_t fn_size;
+	asymbol **org_symtable, **new_symtable;
+
+	fn_size = strlen(filename);
+
+	bfd_init();
+	if ((org_bfd = bfd_openr(filename, bfdname)) == NULL) {
+		bfd_perror(filename);
+		return 1;
+	}
+	if (!bfd_check_format(org_bfd, bfd_object)) {
+		bfd_perror(filename);
+		goto err;
+	}
+
+	bfdname = bfd_get_target(org_bfd);
+	strcpy(tempname, "tmp.XXXXXXX");
+	mktemp(tempname);
+	if ((new_bfd = bfd_openw(tempname, bfdname)) == NULL) {
+		bfd_perror(tempname);
+		goto err;
+	}
+
+	if (!bfd_set_format(new_bfd, bfd_get_format(org_bfd)) ||
+	    !bfd_set_start_address(new_bfd, bfd_get_start_address(org_bfd)) ||
+	    !bfd_set_file_flags(new_bfd, (bfd_get_file_flags(org_bfd) &
+	      bfd_applicable_file_flags(new_bfd))) ||
+	    !bfd_set_arch_mach (new_bfd, bfd_get_arch (org_bfd),
+	      bfd_get_mach (org_bfd))) {
+		bfd_perror(tempname);
+		goto err;
+	}
+	bfd_map_over_sections(org_bfd, setup_section, (void *)new_bfd);
+
+	storage_needed = bfd_get_symtab_upper_bound(org_bfd);
+	if (storage_needed < 0)
+		goto err;
+	if (storage_needed == 0)
+		goto out;
+
+	org_symtable = (asymbol **)malloc(storage_needed);
+	number_of_symbols = bfd_canonicalize_symtab(org_bfd, org_symtable);
+	if (number_of_symbols < 0)
+		goto err;
+
+	new_symtable = (asymbol **)malloc(storage_needed);
+	if (new_symtable == NULL)
+		goto err;
+	name = (char **)calloc(sizeof (char *), number_of_symbols);
+	if (name == NULL)
+		goto err;
+
+	n = 0;
+	for (i = 0; i < number_of_symbols; i++) {
+		const char *symname;
+
+		new_symtable[i] = org_symtable[i];
+		if (!(new_symtable[i]->flags & BSF_GLOBAL))
+			continue;
+
+		symname = bfd_asymbol_name(new_symtable[i]);
+#if 0
+		if (symname[0] == '_')
+			symname++;
+#endif
+		if (in_keep_list(symname))
+			continue;
+
+		n++;
+
+		/*
+		 * make sure there's size for the next entry, even if it's
+		 * as large as it can be.
+		 *
+		 * "_$$hide$$ <filename> <symname><NUL>" ->
+		 *    9 + 3 + sizes of fn and sym name 
+		 */
+		name[i] = (char *)malloc(12 + fn_size + strlen(symname));
+		sprintf(name[i], "_$$hide$$ %s %s", filename, symname);
+		new_symtable[i]->name = name[i];
+	}
+
+	if (n > 0) {
+		struct bfd_cookie cookie;
+
+		new_symtable[number_of_symbols] = NULL;
+		bfd_set_symtab(new_bfd, new_symtable, number_of_symbols);
+
+		cookie.bfd = new_bfd;
+		cookie.symtable = org_symtable;
+		bfd_map_over_sections(org_bfd, copy_section, (void *)&cookie);
+
+		if (!bfd_copy_private_bfd_data(org_bfd, new_bfd)) {
+			bfd_perror("bfd_copy_private_bfd_data");
+			goto err;
+		}
+	}
+
+	bfd_close(new_bfd);
+	bfd_close(org_bfd);
+
+	if (rename(tempname, filename) < 0)
+		perror("rename");
+	unlink(tempname);
+
+	for (i = 0; i < number_of_symbols; i++)
+		if (name[i])
+			free(name[i]);
+	free(new_symtable);
+	free(name);
+
+out:
+	return (rv);
+
+err:
+	rv = 1;
+	if (org_bfd)
+		bfd_close(org_bfd);
+	if (new_bfd) {
+		unlink(tempname);
+		bfd_close(new_bfd);
+	}
+	goto out;
+}
+
+static void
+setup_section(ibfd, isection, arg)
+	bfd *ibfd;
+	sec_ptr isection;
+	PTR arg;
+{
+	sec_ptr osection;
+	bfd *obfd = (bfd *)arg;
+
+	if ((osection = bfd_make_section_anyway(obfd,
+	      bfd_section_name(ibfd, isection))) == NULL ||
+	    !bfd_set_section_size(obfd, osection,
+	      bfd_section_size(ibfd, isection)) ||
+	    !bfd_set_section_vma(obfd, osection,
+	      bfd_section_vma(ibfd, isection)) ||
+	    !bfd_set_section_alignment(obfd, osection,
+	      bfd_section_alignment(ibfd, isection)) ||
+	    !bfd_set_section_flags(obfd, osection,
+	      bfd_get_section_flags(ibfd, isection))) {
+		bfd_perror("setup_section");
+		return;
+	}
+
+	isection->output_section = osection;
+	isection->output_offset = 0;
+	if (!bfd_copy_private_section_data(ibfd, isection, obfd, osection)) {
+		bfd_perror("setup_section");
+		return;
+	}
+}
+
+static void
+copy_section(ibfd, isection, arg)
+	bfd *ibfd;
+	sec_ptr isection;
+	PTR arg;
+{
+	struct bfd_cookie *bc = (struct bfd_cookie *)arg;
+	bfd *obfd = bc->bfd;
+	asymbol **isym = bc->symtable;
+	arelent **relpp;
+	sec_ptr osection;
+	PTR memhunk;
+	bfd_size_type size;
+	long relcount, relsize;
+
+	osection = isection->output_section;
+	size = bfd_get_section_size_before_reloc(isection);
+	if (size == 0 || osection == 0)
+		return;
+
+	relsize = bfd_get_reloc_upper_bound(ibfd, isection);
+	if (relsize < 0) {
+		bfd_perror(bfd_get_filename(ibfd));
+	}
+	if (relsize == 0) {
+		bfd_set_reloc(obfd, osection, NULL, 0);
+	} else {
+		relpp = (arelent **)malloc(relsize);
+		relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, isym);
+		if (relcount < 0)
+			bfd_perror(bfd_get_filename(ibfd));
+		bfd_set_reloc(obfd, osection, relpp, relcount);
+	}
+
+	isection->_cooked_size = isection->_raw_size;
+	isection->reloc_done = true;
+
+	if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS) {
+		memhunk = (PTR)malloc((unsigned int)size);
+		if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size))
+			bfd_perror(bfd_get_filename(ibfd));
+		if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size))
+			bfd_perror(bfd_get_filename(obfd));
+		free(memhunk);
+	} else if (bfd_get_section_flags(ibfd, isection) & SEC_LOAD) {
+		memhunk = (PTR)malloc((unsigned int)size);
+		memset(memhunk, 0, size);
+		if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size))
+			bfd_perror(bfd_get_filename(obfd));
+		free(memhunk);
+	}
+}
--- /dev/null	Mon Nov 11 20:54:40 2002
+++ tools/crunchide/Makefile	Mon Nov 11 02:03:36 2002
@@ -0,0 +1,14 @@
+#	$NetBSD$
+
+NOMAN=	# defined
+
+.include <bsd.own.mk>
+
+HOSTPROGNAME=	${MACHINE_GNU_PLATFORM}-crunchide
+HOST_SRCDIR=	gnu/usr.bin/crunchide
+
+TOOLCHAINOBJ!=	cd ${.CURDIR}/../toolchain && ${PRINTOBJDIR}
+BFDDIR=		${TOOLCHAINOBJ}/build/bfd
+IBERTYDIR=	${TOOLCHAINOBJ}/build/libiberty
+
+.include "${.CURDIR}/../Makefile.host"
>Release-Note:
>Audit-Trail:
>Unformatted: