From:	CRDGW2::CRDGW2::MRGATE::"SMTP::PREP.AI.MIT.EDU::HELP-G++-REQUEST"  1-DEC-1991 22:25:23.91
To:	ARISIA::EVERHART
CC:	
Subj:	Use shared libraries on SunOS 4

From:	help-g++-request@prep.ai.mit.edu@SMTP@CRDGW2
To:	Everhart@Arisia@MRGATE

Received:  by crdgw1.ge.com (5.57/GE 1.115)
	 id AA28318; Sun, 1 Dec 91 22:08:28 EST
Received: by life.ai.mit.edu (4.1/AI-4.10) id AA16895; Sun, 1 Dec 91 20:26:02 EST
Return-Path: <help-g++-request@prep.ai.mit.edu>
Received: from news.cis.ohio-state.edu by life.ai.mit.edu (4.1/AI-4.10) id AA16883; Sun, 1 Dec 91 20:25:43 EST
Received: by news.cis.ohio-state.edu (5.61-kk/5.911008)
	id AA10972; Sun, 1 Dec 91 20:19:18 -0500
Received: from USENET by news.cis.ohio-state.edu with netnews
	for help-g++@prep.ai.mit.edu (help-g++@prep.ai.mit.edu);
	contact usenet@news.cis.ohio-state.edu if you have questions.
To: help-g++@prep.ai.mit.edu
Date: 30 Nov 91 01:38:49 GMT
Message-Id: <CHEN.91Nov30103849@pontiac.ce.osaka-u.ac.jp>
Organization: Osaka University, Osaka, Japan.
From: chen@pontiac.ce.osaka-u.ac.jp (Qian Chen)
Sender: help-g++-request@prep.ai.mit.edu
Subject: Use shared libraries on SunOS 4

I have modified "collect2.c" for SUN-4 running SunOS-4.1.1.
Just compile "collect2.c" using gcc and install it as "gcc-ld"
to the directory where the "gcc-cpp", "gcc-cc1plus" exist.

Here is the source.

/* collect2.c */
/* Build tables of static constructors and destructors and run ld. */
/* Modified by Q.Chen (chen@ce.osaka-u.ac.jp) for using SunOS4 */
/* Hint: hookofile must be linked before libg++.a */

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <malloc.h>

#ifndef ASSEMBLER
#define ASSEMBLER "as"
#endif

#ifndef LINKER
#define LINKER "ld"
#endif

#ifndef NMCMD
#define NMCMD "nm"
#endif

#ifdef DEBUG
#define STATIC static
#else
#define STATIC
#endif

#ifdef convex

#define TEXT_SECTION_ASM_OP ".text"
#define DATA_SECTION_ASM_OP ".data"
#define ASM_GLOBALIZE_LABEL(FILE, LABEL) fprintf (FILE, ".globl _%s\n", LABEL)
#define ASM_OUTPUT_LABEL(FILE, LABEL) fprintf (FILE, "_%s:", LABEL)
#define ASM_OUTPUT_LABELREF(FILE, LABEL) fprintf (FILE, "\tds.w _%s\n", LABEL)

#endif

#if defined(MASSCOMP) || defined(i386)
#define TEXT_SECTION_ASM_OP ".text"
#define DATA_SECTION_ASM_OP ".data"
#define ASM_GLOBALIZE_LABEL(FILE, LABEL) fprintf (FILE, ".globl _%s\n", LABEL)
#define ASM_OUTPUT_LABEL(FILE, LABEL) fprintf (FILE, "_%s:\n", LABEL)
#define ASM_OUTPUT_LABELREF(FILE, LABEL)  fprintf (FILE, "\t.long _%s\n", LABEL)
#define ASM_OUTPUT_INT(FILE, INT) fprintf (FILE, "\t.long %d\n", INT)

#endif

#if defined (sun) || defined (__sun__)

#if defined (sparc) || defined (__sparc__)

#define TEXT_SECTION_ASM_OP ".text"
#define DATA_SECTION_ASM_OP ".data"
#define ASM_GLOBALIZE_LABEL(FILE, LABEL) fprintf (FILE, ".global _%s\n", LABEL)
#define ASM_OUTPUT_LABEL(FILE, LABEL) fprintf (FILE, "_%s:\n", LABEL)
#define ASM_OUTPUT_LABELREF(FILE, LABEL) fprintf (FILE, "\t.word _%s\n", LABEL)
#define ASM_OUTPUT_INT(FILE, INT) fprintf (FILE, "\t.word %d\n", INT)

#else

#if defined (mc68020) || defined (__mc68000__) || defined (mc68000)

#define TEXT_SECTION_ASM_OP ".text"
#define DATA_SECTION_ASM_OP ".data"
#define ASM_GLOBALIZE_LABEL(FILE, LABEL) fprintf (FILE, ".globl _%s\n", LABEL)
#define ASM_OUTPUT_LABEL(FILE, LABEL) fprintf (FILE, "_%s:\n", LABEL)
#define ASM_OUTPUT_LABELREF(FILE, LABEL) fprintf (FILE, "\t.long _%s\n", LABEL)
#define ASM_OUTPUT_INT(FILE, INT) fprintf (FILE, "\t.long %d\n", INT)

#endif /* mc68020 */
#endif /* sparc */
#endif /* sun */

/* Linked lists of constructor and destructor names. */

struct id {
	char *name;
	struct id *next;
};


extern char *mktemp(char *template);
extern int unlink(char *filename);

STATIC void write_hooks(FILE *inf, FILE *outf);

STATIC int count_list(struct id *list);

STATIC void write_list(FILE *outf, struct id *list);

STATIC void cleantmps(void);

STATIC void inserthook(char *ldcmd, int argc, char **argv, char *hookname);

STATIC void lnkcmd(char *ldcmd, int argc, char **argv, char *codefile);

/* gcc make string constant read only,
 * and mktemp() do write on its arguement.
 */

static char hooksfile[128], hookofile[128], *listfile = 0;
static char nmname[128] = "/tmp/gpnmXXXXXX";


/* Main program. */

int main (int argc, char **argv)
{
	char *hookfile;
	static char hookname[128] = "/tmp/gplusXXXXXX", ldcmd[1024];
	FILE *inf, *outf;

	/* Make temp file names. */

	listfile = mktemp(nmname);
	hookfile = mktemp(hookname);
	sprintf (hooksfile, "%s.s", hookfile);
	sprintf (hookofile, "%s.o", hookfile);

	/* Cleanup when interrupted. */

	signal(SIGINT, cleantmps); /* deleting temprary files. */

	/* Parse arguments. Build the command line of first link. */

	lnkcmd(ldcmd, argc, argv, hookofile);
	strcat(ldcmd, " > /dev/null 2>&1 > /dev/null");
#ifdef DEBUG
	fprintf(stderr, "%s\n", ldcmd);
#endif
	system(ldcmd); /* do not check return value */

	/* Build name list */
	sprintf(ldcmd, "%s %s > %s", NMCMD, hookofile, listfile);
#ifdef DEBUG
	fprintf(stderr, "%s\n", ldcmd);
#endif
	if (system(ldcmd) != 0) {
		cleantmps();
		fprintf(stderr, "%s failed.\n", argv[0]);
		return(1);
	};

	/* Scan name list, build constructor and deconstructor list */

	if ((inf = fopen (listfile, "r")) == NULL) {
		fprintf (stderr, "%s: Can't open output of nm: %s\n", argv[0], listfile);
		cleantmps();
		return(1);
	};
	if ((outf = fopen (hooksfile, "w")) == NULL) {
		fprintf (stderr, "%s: Can't open hooksfile: %s\n", argv[0], hooksfile);
		cleantmps();
		return(1);
	};
	write_hooks(inf, outf);
	fclose (inf);
	fclose (outf);
	unlink(listfile);

	/* Assemble the constructor and destructor tables. */

	sprintf(ldcmd, "%s -o %s %s", ASSEMBLER, hookofile, hooksfile);
#ifdef DEBUG
	fprintf(stderr, "%s\n", ldcmd);
#endif
	if (system(ldcmd) != 0) {
		fprintf(stderr, "%s: Can't assemble %s.\n", argv[0], hooksfile);
		cleantmps();
		return(1);
	};
	unlink(hooksfile);

	/* Build command line of real link.
	 * Insert hookofile in the link list.
	 * Link the tables in with the rest of the program.
	 */

	inserthook(ldcmd, argc, argv, hookofile);
	if (system(ldcmd) != 0) {
		fprintf(stderr, "%s: Link failed.\n", argv[0]);
		cleantmps();
		return(1);
	};
	unlink(hookofile);
	return(0);
}

STATIC void inserthook(char *ldcmd, int argc, char **argv, char *hookname)
{
	int i, n, len;
	char *arg;

	n = 0;
	for (i = 1; i < argc; ++i) {
		arg = argv[i];
		len = strlen(arg);
		if (len >= 3 && arg[len - 2] == '.' && arg[len - 1] == 'o') {
			n = i;
		};
	};
	strcpy(ldcmd, LINKER);
	for (i = 1; i <= n; ++i) {
#ifdef masscomp
		if (argv[i][0] == '-' && argv[i][1]) == 'L') {
			strcat (ldcmd, " -L ");
			strcat (ldcmd, argv[i][2]);
			continue;
		};
#endif
		strcat(ldcmd, " ");
		strcat(ldcmd, argv[i]);
	};
	strcat(ldcmd, " ");
	strcat(ldcmd, hookname);
	for (i = n + 1; i < argc; ++i) {
#ifdef masscomp
		if (argv[i][0] == '-' && argv[i][1]) == 'L') {
			strcat (ldcmd, " -L ");
			strcat (ldcmd, argv[i][2]);
			continue;
		};
#endif
		strcat(ldcmd, " ");
		strcat(ldcmd, argv[i]);
	};
/*
#if defined(sun) && !defined(NO_DYNAMIC_LIBS)
	strcat(ldcmd, " -Bdynamic -ldl");
#endif
*/
}

STATIC void lnkcmd(char *ldcmd, int argc, char **argv, char *codefile)
{
	int ct;
	char *arg;

	sprintf(ldcmd, "%s -o %s", LINKER, codefile);
	ct = 1;
	while (ct < argc) {
		arg = argv[ct];
		++ct;
		if (strcmp(arg, "-o") == 0) {
			++ct;
			continue;
		};
#ifdef masscomp
		if (*arg == '-' && *(arg + 1) == 'L') {
			strcat (ldcmd, " -L ");
			strcat (ldcmd, arg + 2);
			continue;
		};
#endif
		strcat(ldcmd, " ");
		strcat(ldcmd, arg);
	};
}

/* Length of list LIST. */

STATIC int count_list (struct id *list)
{
	int count = 0;

	while (list != NULL) {
		count++;
		list = list->next;
	}
	return(count);
}


/* Write the names on list LIST, in reverse order. */

STATIC void write_list (FILE *outf, struct id *list)
{
	if (list != NULL) {
		write_list (outf, list->next);
		ASM_OUTPUT_LABELREF (outf, list->name);
	};
}

STATIC void cleantmps(void)
{
	unlink(listfile);
	unlink(hooksfile);
	unlink(hookofile);
}
/* Scan the name list of the loaded program for the symbols g++ uses
   for static constructors and destructors.  Write their addresses
   into tables which __main and exit will call.

   The constructor table __CTOR_LIST__ is an integer count followed by
   that many pointers to constructor functions.  The destructor table
   __DTOR_LIST__ is the same thing, followed by a zero word. */


STATIC void write_hooks(FILE *inf, FILE *outf)
{
	char *p;
	static char buf[1024];
	struct id *newid;

	struct id *constructors = 0;
	struct id *destructors = 0;

	while (! feof (inf)) {
		/* Read a line of nm output and strip the trailing newline. */

		fgets (buf, sizeof buf, inf);
		p = buf + strlen (buf) - 1;
		if (*p == '\n') *p = '\0';

#ifdef masscomp
		/* If loader spits out an error/warning message then
		 * lets display it.
		 */
		if (buf[0] == '#' && buf[1] == '#') {
			fprintf(stderr, "%s\n", buf );
			buf[0] = '\0';
		};
#endif
		/* If it contains a constructor or destructor name, add the name
		   to the appropriate list. */

		for (p = buf; *p != 0; p++) {
			while (*p != 0 && *p != '_') p++;
			if (strncmp (p, "_GLOBAL_$I$", 11) == 0) {
				newid = malloc (sizeof *newid);
				newid->name = malloc (strlen (p) + 1);
				strcpy (newid->name, p);
				newid->next = constructors;
				constructors = newid;
				break;
			}
			else if (strncmp (p, "_GLOBAL_$D$", 11) == 0) {
				newid = malloc (sizeof *newid);
				newid->name = malloc (strlen (p) + 1);
				strcpy (newid->name, p);
				newid->next = destructors;
				destructors = newid;
				break;
			};
		};
	};


	/* Write the tables. */

	fprintf (outf, "%s\n", TEXT_SECTION_ASM_OP);
	ASM_GLOBALIZE_LABEL (outf, "__CTOR_LIST__");
	ASM_OUTPUT_LABEL (outf, "__CTOR_LIST__");
	ASM_OUTPUT_INT (outf, count_list (constructors));
	write_list (outf, constructors);
	ASM_OUTPUT_INT (outf, 0);

	fprintf (outf, "%s\n", DATA_SECTION_ASM_OP);
	ASM_GLOBALIZE_LABEL (outf, "__DTOR_LIST__");
	ASM_OUTPUT_LABEL (outf, "__DTOR_LIST__");
	ASM_OUTPUT_INT (outf, count_list (destructors));
	write_list (outf, destructors);
	ASM_OUTPUT_INT (outf, 0);

	while (constructors != NULL) {
		newid = constructors->next;
		free(constructors->name);
		free(constructors);
		constructors = newid;
	};
	while (destructors != NULL) {
		newid = destructors->next;
		free(destructors->name);
		free(destructors);
		destructors = newid;
	};
}

/* --- end ---- end ---- end ---- end ---- end ---- */




				





--
	Qian Chen

            Lab                   |            HOME
Department of Control Engineering | B628
Osaka University                  | Osaka University International House
Tel: 06-844-1151 (ex 4619)        | Tel: 06-855-9210
email: chen@ce.osaka-u.ac.jp      |

                        1-1 Machikaneyama
                        Toyonaka, Osaka
                        560 Japan
