Author: Jyrki Kuoppala (jkp@cs.hut.fi) Last modified: Sun Apr 23 12:14:18 1989 Problems: object files compiled with 'cc -g' confuse robotussin. diff -cr2N bu.orig/ALTOS-README bu/ALTOS-README *** bu.orig/ALTOS-README Thu Jan 1 03:00:00 1970 --- bu/ALTOS-README Sun Apr 23 02:46:06 1989 *************** *** 0 **** --- 1,53 ---- + Return-Path: + Date: Mon, 10 Apr 89 10:13:45 +0300 + From: Jyrki Kuoppala + Sender: jkp@sauna.hut.fi + To: info-gcc@prep.ai.mit.edu + Subject: Kernel fix needed for Altos 3068 to get coff-encapsulation working right + Organization: Helsinki University of Technology, Finland. + + Here's a description how to fix a kernel bug in Altos 3068 and get + gcc-compiled programs working. + + Author: Jyrki Kuoppala (jkp@cs.hut.fi) + Last modified: Mon Apr 10 09:28:40 1989 + + There's a bug in the Altos 3068 kernel that causes gcc-compiled + programs to fail in certain situations when the machine has a heavy + load and also in some other situations. The bug exists at least in + SVR 2.2 1.0gT1 and SVR 2.2 1.0e. + + If you have source code to your system, apply the following change to + os/exec.c (function gethead): + + Change the lines containing + + u.u_exdata.ux_tstart = sizeof(struct naout) + + sizeof(struct filhd) + (ep->ef.nscns * sizeof(struct scnhdr)); + + to + + u.u_exdata.ux_tstart = u.u_exdata.ux_txtorg; + + If you only have binary, use sdb to find out the address of the + previous lines (on our system it's gethead+0x140) and use your + favourite binary editor to change the bytes '3036 0162 fffc 0002 0280 + 0000' to '23f9 01fb f4ca 01fb f4c2 6016'. This may or may not work in + your case, depending on the version of the operating system and the + phase of the moon. + + Here's what is just before gethead+0x140 to ease finding out the right place: + + 0x9224 (gethead+0x122): 23f9 01fb f4ca 01fb f4ce mov.l &0x1fbf4ca.L,&0 + x1fbf4ce.L [] + 0x922e (gethead+0x12c): 23f9 01fb f4c6 01fb f4ca mov.l &0x1fbf4c6.L,&0 + x1fbf4ca.L [] + 0x9238 (gethead+0x136): 23f9 01fb f4c2 01fb f4c6 mov.l &0x1fbf4c2.L,&0 + x1fbf4c6.L [] + + Good luck ! + + //Jyrki + + jkp@cs.hut.fi + diff -cr2N bu.orig/Makefile bu/Makefile *** bu.orig/Makefile Sun Apr 23 02:16:09 1989 --- bu/Makefile Sun Apr 23 11:38:09 1989 *************** *** 21,30 **** GNUCC = gcc -O # for BSD systems ! CFLAGS = -g # Don't add robotussin; it won't compile on BSD or GNU systems. # objdump also won't compile on most systems (trouble with N_DATADDR). ! PROGS = gprof ld size nm strip ar ranlib # for USG systems using COFF_ENCAPSULATE --- 21,31 ---- GNUCC = gcc -O + CC = gcc -O # for BSD systems ! #CFLAGS = -g # Don't add robotussin; it won't compile on BSD or GNU systems. # objdump also won't compile on most systems (trouble with N_DATADDR). ! #PROGS = gprof ld size nm strip ar ranlib # for USG systems using COFF_ENCAPSULATE *************** *** 32,37 **** # Note that you should leave a copy of `ar' in this directory # after you install it, since `ranlib' will try to run it from here. ! #CFLAGS = -g -DUSG -DCOFF_ENCAPSULATE -DPORTAR -DNON_NATIVE ! #PROGS = ld size nm strip ar robotussin objdump ranlib gprof #it's better to move a copy of alloca into your libc than to risk getting some #incompatiable functions from -lPW (like index()), but if you --- 33,38 ---- # Note that you should leave a copy of `ar' in this directory # after you install it, since `ranlib' will try to run it from here. ! CFLAGS = -g -DUSG -DCOFF_ENCAPSULATE -DPORTAR -DNON_NATIVE ! PROGS = ld size nm strip ar robotussin objdump ranlib gprof #it's better to move a copy of alloca into your libc than to risk getting some #incompatiable functions from -lPW (like index()), but if you *************** *** 76,80 **** $(CC) -o ranlib ranlib.o ranlib.o: ranlib.c ! $(CC) -c -g -DAR_PROG=\"`pwd`/ar\" ranlib.c # Robotussin is NOT part of `all'. --- 77,81 ---- $(CC) -o ranlib ranlib.o ranlib.o: ranlib.c ! $(CC) -c $(CFLAGS) -DAR_PROG=\"`pwd`/ar\" ranlib.c # Robotussin is NOT part of `all'. diff -cr2N bu.orig/a.out.encap.h bu/a.out.encap.h *** bu.orig/a.out.encap.h Sun Apr 23 02:16:11 1989 --- bu/a.out.encap.h Sun Apr 23 02:35:32 1989 *************** *** 81,86 **** #define COFF_MAGIC 0514 /* I386MAGIC */ #endif ! #if defined(i386) short __header_offset_temp; #define HEADER_OFFSET(f) \ --- 81,89 ---- #define COFF_MAGIC 0514 /* I386MAGIC */ #endif + #ifdef m68k + #define COFF_MAGIC 0520 /* MC68MAGIC */ + #endif ! #if defined(i386) || defined(m68k) short __header_offset_temp; #define HEADER_OFFSET(f) \ *************** *** 120,124 **** ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \ sizeof (struct coffheader) + sizeof (struct exec) : 0) ! #define SEGMENT_SIZE 0x400000 #define N_DATADDR(x) \ --- 123,135 ---- ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \ sizeof (struct coffheader) + sizeof (struct exec) : 0) ! /* This is altos 3068-specific, but there isn't any good #define for it */ ! #if defined(m68k) && defined(PORTAR) ! #define SEGMENT_SIZE 0x40000 ! #define N_DATADDR(x) \ ! ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \ ! (((N_TXTADDR(x)+(x).a_text+0x2000) / SEGMENT_SIZE + 1) * SEGMENT_SIZE + \ ! (N_TXTADDR(x)+(x).a_text+0x2000) % 0x2000) : \ ! (N_TXTADDR(x)+(x).a_text)) ! #else #define SEGMENT_SIZE 0x400000 #define N_DATADDR(x) \ *************** *** 126,127 **** --- 137,139 ---- (SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))) : \ (N_TXTADDR(x)+(x).a_text)) + #endif /* m68k && PORTAR */ diff -cr2N bu.orig/getopt.c bu/getopt.c *** bu.orig/getopt.c Sun Apr 23 02:16:14 1989 --- bu/getopt.c Sun Apr 23 03:10:44 1989 *************** *** 34,42 **** --- 34,48 ---- #include + /* If compiled with GNU C, use the built-in alloca */ + #ifdef __GNUC__ + #define alloca __builtin_alloca + #else #ifdef sparc #include #endif + #endif #ifdef USG #define bcopy(s, d, l) memcpy((d), (s), (l)) + #define index strchr #endif diff -cr2N bu.orig/ld.c bu/ld.c *** bu.orig/ld.c Sun Apr 23 02:16:20 1989 --- bu/ld.c Sun Apr 23 12:01:46 1989 *************** *** 2,5 **** --- 2,9 ---- Copyright (C) 1988 Free Software Foundation, Inc. + Hacked by Michael Tiemann (tiemann@mcc.com) + Sun4 support by Gary Beihl (beihl@mcc.com) + Merged with ld++ by Jyrki Kuoppala (jkp@cs.hut.fi) + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by *************** *** 146,149 **** --- 150,156 ---- #define INITIALIZE_HEADER N_SET_MACHTYPE (outheader, M_386) #endif + #ifdef m68k + #define INITIALIZE_HEADER N_SET_MACHTYPE (outheader, M_68020) + #endif #ifdef is68k *************** *** 716,719 **** --- 723,778 ---- int make_executable; + /* C++: Take care of global constructors and destructors. */ + void symtab_init_for_cplusplus (); + + /* Nonzero if we are doing fancies for C++. */ + int cplusplus = 0; + + /* Name for file containing (temporary) constructor and destructor + information. This file is in a.out.h format, alas. */ + #ifndef L_tmpnam + #define L_tmpnam 32 + #endif + char ctor_and_dtor_filename[L_tmpnam]; + + /* Data for list of global constructors and destructors respectively. */ + symbol **ctor_vec, **dtor_vec; + + /* Sizes of the respective vectors. */ + int ctor_size_max, dtor_size_max; + + /* Current sizes of the respective vectors. */ + int ctor_size = 0, dtor_size = 0; + + /* nonzero if we are looking for global constructors and + destructors. This starts out nonzero, and is cleared + after the files have all been seen once. + + In the case of incremental loading, it is reset + when loading symbol information from the executing + program (the ctors and dtors have already been put in + place), and set for each additional file which + is added. */ + int looking_for_ctors_and_dtors = 0; + + /* The symbols that crt0+.c expects to find in order to + call the global constructors and destructors for the + program. */ + symbol *ctor_list_symbol; + symbol *dtor_list_symbol; + + /* For incremental loading, this will be patched to point to + the initial function of the code being incrementally loaded. */ + symbol *init_symbol; + + /* For incremental loading, this is the head and tail of the + new list of destructors to call. */ + symbol *head_dtor_symbol, *tail_dtor_symbol; + + void layout_ctors_and_dtors (); + + /* 1 if the -A flag has been specified, 0 otherwise. */ + int A_flag_specified; + /* Force the executable to be output, even if there are non-fatal errors */ *************** *** 824,827 **** --- 883,889 ---- symtab_init (); + if (cplusplus) + symtab_init_for_cplusplus (); + /* Determine whether to count the header as part of the text size, and initialize the text size accordingly. *************** *** 857,862 **** /* Load symbols of all input files. ! Also search all libraries and decide which library members to load. */ load_symbols (); --- 919,927 ---- /* Load symbols of all input files. ! Also search all libraries and decide which library members to load. + C++: this does not include the fake ctor and dtor file. That file + is created on entry to `digest_symbols'. */ + load_symbols (); *************** *** 879,882 **** --- 944,950 ---- write_output (); + if (cplusplus && unlink (ctor_and_dtor_filename)) + perror_file (&file_table[number_of_files-1]); + return ! make_executable; } *************** *** 967,972 **** fatal ("no input files", 0); p = file_table ! = (struct file_entry *) xmalloc (number_of_files * sizeof (struct file_entry)); bzero (p, number_of_files * sizeof (struct file_entry)); --- 1035,1042 ---- fatal ("no input files", 0); + /* Since we haven't parsed options yet, we don't know if we are + ld++. So play safe and allocate one more anyhow. */ p = file_table ! = (struct file_entry *) xmalloc ((number_of_files + 1) * sizeof (struct file_entry)); bzero (p, number_of_files * sizeof (struct file_entry)); *************** *** 994,997 **** --- 1064,1068 ---- p->local_sym_name = string; p->just_syms_flag = 1; + A_flag_specified = 1; p++; } *************** *** 1096,1099 **** --- 1167,1174 ---- return; + /* We silently ignore -B options. */ + case 'B': + return; + case 'D': specified_data_size = parse (arg, "%x", "invalid argument to -D"); *************** *** 1190,1193 **** --- 1265,1274 ---- return; + /* C++ extension. */ + case 'C': + cplusplus = 1; + looking_for_ctors_and_dtors = 1; + return; + default: fatal ("invalid command option `%s'", swt); *************** *** 1215,1218 **** --- 1296,1301 ---- { register struct file_entry *entry = &file_table[i]; + if (cplusplus && A_flag_specified) + looking_for_ctors_and_dtors = i != 0; if (entry->library_flag) { *************** *** 1613,1617 **** all such structs that refer to the same global symbol. This chain starts in the `refs' field of the symbol table entry ! and is chained through the `n_name'. */ void --- 1696,1703 ---- all such structs that refer to the same global symbol. This chain starts in the `refs' field of the symbol table entry ! and is chained through the `n_name'. ! ! C++: if this symbol is a global constructor or destructor, ! make a note of it. */ void *************** *** 1632,1635 **** --- 1718,1726 ---- if (type != (N_UNDF | N_EXT) || nlist_p->n_value) { + #ifdef nounderscore + #define CTOR_OR_DTOR_PREFIX "_GLOBAL_$" + #else + #define CTOR_OR_DTOR_PREFIX "__GLOBAL_$" + #endif sp->defined = 1; if (oldref && !olddef) *************** *** 1640,1643 **** --- 1731,1735 ---- && sp->max_common_size < nlist_p->n_value) sp->max_common_size = nlist_p->n_value; + if (SET_ELEMENT_P (type) && !olddef) set_vector_count++; *************** *** 1651,1654 **** --- 1743,1775 ---- global_indirect_count++; } + + /* C++: global constructors and destructors are only + ever defined. They are never multiply defined, + unless a file is duplicated on the command line. + In that case, other errors will be reported. */ + + if (looking_for_ctors_and_dtors + && ! strncmp (sp->name, CTOR_OR_DTOR_PREFIX, + sizeof (CTOR_OR_DTOR_PREFIX)-1)) + { + if (sp->name[sizeof (CTOR_OR_DTOR_PREFIX)-1] == 'I') + { + if (ctor_size >= ctor_size_max) + { + ctor_size_max <<= 1; + ctor_vec = (symbol **)xrealloc (ctor_vec, ctor_size_max); + } + ctor_vec[ctor_size++] = sp; + } + else + { + if (dtor_size >= dtor_size_max) + { + dtor_size_max <<= 1; + dtor_vec = (symbol **)xrealloc (dtor_vec, dtor_size_max); + } + dtor_vec[dtor_size++] = sp; + } + } } else *************** *** 2124,2127 **** --- 2245,2635 ---- } + /* Do what must be done *after* decoding argv. */ + void + symtab_init_for_cplusplus () + { + /* Make this contain a deterministic value which + we can try to remove if necessary. */ + strcpy (ctor_and_dtor_filename, "C++.hacksXXXXXX"); + + /* C++: these are the names that crt0+.c looks for. */ + #ifndef nounderscore + if (A_flag_specified) + { + ctor_list_symbol = getsym ("__xCTOR_LIST__"); + dtor_list_symbol = getsym ("__xDTOR_LIST__"); + + head_dtor_symbol = getsym("__head"); + tail_dtor_symbol = getsym("__tail"); + init_symbol = getsym("__initfn"); + } + else + { + ctor_list_symbol = getsym ("___CTOR_LIST__"); + dtor_list_symbol = getsym ("___DTOR_LIST__"); + } + #else + if (A_flag_specified) + { + ctor_list_symbol = getsym ("_xCTOR_LIST__"); + dtor_list_symbol = getsym ("_xDTOR_LIST__"); + + head_dtor_symbol = getsym("_head"); + tail_dtor_symbol = getsym("_tail"); + init_symbol = getsym("_initfn"); + } + else + { + ctor_list_symbol = getsym ("__CTOR_LIST__"); + dtor_list_symbol = getsym ("__DTOR_LIST__"); + } + #endif + + /* C++: initialize ctor and dtor vectors. */ + ctor_size = 0; + ctor_size_max = 120; + dtor_size = 0; + dtor_size_max = 120; + ctor_vec = (symbol **) xmalloc (ctor_size_max * sizeof (symbol *)); + dtor_vec = (symbol **) xmalloc (dtor_size_max * sizeof (symbol *)); + + if (A_flag_specified) + { + ctor_list_symbol->defined = N_DATA; + dtor_list_symbol->defined = N_DATA; + init_symbol->defined = N_DATA; + head_dtor_symbol->defined = N_DATA; + tail_dtor_symbol->defined = N_DATA; + + init_symbol->referenced = 1; + head_dtor_symbol->referenced = 1; + tail_dtor_symbol->referenced = 1; + + head_dtor_symbol->trace = 1; + tail_dtor_symbol->trace = 1; + init_symbol->trace = 1; + } + else + { + ctor_list_symbol->defined = N_TEXT | N_EXT; + dtor_list_symbol->defined = N_DATA | N_EXT; + } + ctor_list_symbol->referenced = 1; + dtor_list_symbol->referenced = 1; + } + + /* C++: Having found all of the file modules we will need, and found, + for each module, the global constructor and/or destructor it + will need, lay out the table of constructors and destructors. + + The format of the constructor table is an integer length, + followed by a list of function pointers. The list is 0 + terminated, for good luck. The length includes the size + of the length field, but does not include the 0 terminating + entry. + + The format of the destructor table is a linked list of + elements. Each element is a pair consisting of a next pointer + and a function pointer. The list is built in this function. + + Layout of symbol numbers: + + 0 for ctor_list_symbol + 1 for dtor_list_symbol + 2 .. ctor_size-1 for ctors + 2 + ctor_size .. 2 + ctor_size + dtor_size - 1 for dtors + 2 + ctor_size + dtor_size for _head + 2 + ctor_size + dtor_size + 1 for _tail + 2 + ctor_size + dtor_size + 2 for _initfn. + + */ + void + layout_ctors_and_dtors () + { + struct file_entry *entry = &file_table[number_of_files]; + struct exec *header = &entry->header; + int this_text_size = sizeof (int) * (ctor_size + 1); + int this_data_size = sizeof (int) * (1 + 2 * dtor_size); + char *strp; /* end of entry->strings, if any */ + FILE *fp; + int i, strindex = sizeof (int); + struct nlist nl; + struct relocation_info r1, r2; + + struct + { + union + { + struct dtor_list_elem *next; + int offset; + } u; + void (*pf)(); + } dtor_list_elem; + + if (input_file) file_close (); + + number_of_files += 1; /* now add this file. */ + + if ((fp = fopen (mktemp (ctor_and_dtor_filename), "w")) == NULL) + fatal ("could not open file for global constructors and destructors"); + entry->filename = ctor_and_dtor_filename; + entry->local_sym_name = ctor_and_dtor_filename; + + /* Now make header correspond to new reality. */ + + N_SET_MAGIC (*header, OMAGIC); + #ifdef INITIALIZE_HEADER + INITIALIZE_HEADER; + #endif + + header->a_text = this_text_size; + header->a_data = this_data_size; + header->a_bss = 0; + header->a_entry = 0; + header->a_trsize = sizeof (struct relocation_info) * ctor_size; + header->a_drsize = sizeof (struct relocation_info) * (2 * dtor_size); + header->a_syms = sizeof (struct nlist) * (2 + ctor_size + dtor_size); + + if (fwrite (header, sizeof (struct exec), 1, fp) != 1) + fatal ("error writing header"); + + /* Automagically fill text segment with 0 up to this address. */ + fseek (fp, this_text_size, 1); + + /* Now write out data information. */ + /* First, point __DTOR_LIST__ at its table. */ + if (dtor_size) + dtor_list_elem.u.offset = sizeof (int); + else + dtor_list_elem.u.offset = 0; + if (fwrite (&dtor_list_elem.u.offset, sizeof (int), 1, fp) != 1) + fatal ("error writing destructor list head"); + + /* Now, write out the offsets for the table. */ + dtor_list_elem.pf = (void (*)())0; + for (i = 0; i < dtor_size-1; i++) + { + dtor_list_elem.u.offset = (2*(i+1)+1) * sizeof (int); + if (fwrite (&dtor_list_elem, sizeof (dtor_list_elem), 1, fp) != 1) + fatal ("error writing destructor list elements"); + } + if (dtor_size) + { + /* Space for last element. */ + fseek (fp, sizeof (dtor_list_elem), 1); + } + + /* Do relocation. Initialize invariant data. */ + bzero(&r1, sizeof(r1)); + bzero(&r2, sizeof(r2)); + #if defined(sun) && (TARGET == SUN4) + r1.r_type = RELOC_32; + r1.r_extern = 1; + r2.r_type = RELOC_32; + r2.r_extern = 1; + #else + r1.r_length = 2; + r1.r_extern = 1; + r2.r_length = 2; + r2.r_extern = 1; + #endif + + /* Now do text relocation. */ + for (i = 0; i < ctor_size; i++) + { + /* relocation for the pointer to constructor function. */ + r1.r_address = i * sizeof (int); + r1.r_symbolnum = i + 2; + if (fwrite (&r1, sizeof (struct relocation_info), 1, fp) != 1) + fatal ("error writing relocation info to global constructor file"); + } + + /* Now do data relocation. */ + r1.r_symbolnum = 1; + + if (dtor_size) + { + /* Point __DTOR_LIST__ at its table. */ + r1.r_address = 0; + #if defined(sun) && (TARGET == SUN4) + /* Really point __DTOR_LIST__ at its table. The + sparc loader does not add the address being relocated + to its relocation address. */ + r1.r_addend = 4; + #endif + if (fwrite (&r1, sizeof (struct relocation_info), 1, fp) != 1) + fatal ("error writing relocation info to global destructor file"); + } + + /* Now, build the table. */ + for (i = 0; i < dtor_size-1; i++) + { + /* relocation for the `next' pointer. */ + r1.r_address = (2*i + 1) * sizeof (int); + #if defined(sun) && (TARGET == SUN4) + /* Really point __DTOR_LIST__[i] at &__DTOR_LIST__[i+1]. The + sparc loader does not add the address being relocated + to its relocation address. */ + r1.r_addend = (2*i + 3) * sizeof (int); + #endif + + /* relocation for the pointer to destructor function. */ + r2.r_address = (2*i + 1 + 1) * sizeof (int); + /* Call destructors in reverse order. */ + r2.r_symbolnum = 2 + ctor_size + ((dtor_size-1) - i); + + if (fwrite (&r1, sizeof (struct relocation_info), 1, fp) != 1 + || fwrite (&r2, sizeof (struct relocation_info), 1, fp) != 1) + fatal ("error writing relocation info to global destructor file"); + } + + if (dtor_size) + { + /* relocation for the last element's function pointer. */ + r2.r_address = (2 * dtor_size) * sizeof (int); + r2.r_symbolnum = 2 + ctor_size; + if (fwrite (&r2, sizeof (struct relocation_info), 1, fp) != 1) + fatal ("error writing relocation info to global destructor file"); + } + + /* Now write out the symbol information. */ + + entry->symbols = (struct nlist *)xmalloc (sizeof (struct nlist) * (2 + ctor_size + dtor_size)); + + nl.n_other = 0; + nl.n_desc = 0; + + nl.n_type = N_TEXT | N_EXT; + nl.n_un.n_strx = strindex; + nl.n_value = 0; + strindex += strlen (ctor_list_symbol->name) + 1; + entry->symbols[0] = nl; + + nl.n_type = N_DATA | N_EXT; + nl.n_un.n_strx = strindex; + nl.n_value = this_text_size; + strindex += strlen (dtor_list_symbol->name) + 1; + entry->symbols[1] = nl; + + nl.n_type = N_UNDF | N_EXT; + nl.n_value = 0; + + for (i = 0; i < ctor_size; i++) + { + symbol *sp = ctor_vec[i]; + nl.n_un.n_strx = strindex; + strindex += strlen (sp->name) + 1; + entry->symbols[i+2] = nl; + } + + for (i = 0; i < dtor_size; i++) + { + symbol *sp = dtor_vec[i]; + nl.n_un.n_strx = strindex; + strindex += strlen (sp->name) + 1; + entry->symbols[ctor_size + i + 2] = nl; + } + + if (fwrite (entry->symbols, sizeof (struct nlist), + 2 + ctor_size + dtor_size, fp) + != 2 + ctor_size + dtor_size) + fatal ("error writing symbol entries"); + + entry->string_size = strindex; + + /* If entry thinks it has strings, it is wrong. But + we will now give it correct strings. */ + if (entry->strings) + fatal ("strings non-null in layout_ctors_and_dtors"); + + entry->strings = (char *)alloca (strindex + sizeof (int)); + strp = entry->strings; + *((int *)strp) = strindex; + strp += sizeof (int); + + strcpy (strp, ctor_list_symbol->name); + strp += strlen (strp) + 1; + strcpy (strp, dtor_list_symbol->name); + strp += strlen (strp) + 1; + + for (i = 0; i < ctor_size; i++) + { + symbol *sp = ctor_vec[i]; + strcpy (strp, sp->name); + strp += strlen (strp) + 1; + } + + for (i = 0; i < dtor_size; i++) + { + symbol *sp = dtor_vec[i]; + strcpy (strp, sp->name); + strp += strlen (strp) + 1; + } + + if (fwrite (entry->strings, strp - entry->strings, 1, fp) != 1) + fatal ("error writing strings"); + + looking_for_ctors_and_dtors = 0; + enter_file_symbols (entry); + entry->strings = 0; + fclose (fp); + } + + /* When we know what we need to know for crt1+.o to be + happy, patch the data to do so. */ + void + patch_data (bytes) + char *bytes; + { + /* Fixup the _head, _tail, and _initfn pointers. */ + struct nlist *p; + struct file_entry *entry = &file_table[1]; /* Assume crt1+.o is 1th. */ + struct file_entry *last_entry = &file_table[number_of_files-1]; + int to_do = 4; + int *ints = (int *)bytes; + int *doffset = (int *)entry->data_start_address; + + entry->strings = (char *) alloca (entry->string_size); + read_entry_strings (file_open (entry), entry); + + for (p = entry->symbols; to_do; p++) + if (!(p->n_type & (N_STAB | N_EXT))) + { + char *symname = entry->strings + p->n_un.n_strx; + + if (symname[0] != '_') + continue; + + if (! strcmp (ctor_list_symbol->name, symname)) + { + ints[(int *)p->n_value - doffset] + = last_entry->text_start_address; + to_do--; + } + if (! strcmp (head_dtor_symbol->name, symname)) + { + ints[(int *)p->n_value - doffset] + = dtor_size ? last_entry->data_start_address + sizeof (int) : 0; + to_do--; + } + else if (! strcmp (tail_dtor_symbol->name, symname)) + { + ints[(int *)p->n_value - doffset] = dtor_size + ? (last_entry->data_start_address + + last_entry->header.a_data - 2 * sizeof (int)) + : 0; + to_do--; + } + else if (! strcmp (init_symbol->name, symname)) + { + ints[(int *)p->n_value - doffset] + = file_table[2].text_start_address; + to_do--; + } + } + entry->strings = 0; + } + + void consider_file_section_lengths (), relocate_file_addresses (); *************** *** 2142,2145 **** --- 2650,2661 ---- fprintf (stderr, "Digesting symbol information:\n\n"); + /* C++: Now that we know what modules are required, build + the tables of calls for the global constructors and + destructors. This function will act if we are doing a + normal executable. */ + + if (cplusplus) + layout_ctors_and_dtors (); + /* Compute total size of sections */ *************** *** 4225,4232 **** struct file_entry *entry; { ! fprintf (stderr, "ld: "); fprintf (stderr, string); print_file_name (entry, stderr); fprintf (stderr, "\n"); exit (1); } --- 4741,4750 ---- struct file_entry *entry; { ! fprintf (stderr, cplusplus ? "ld++: " : "ld: "); fprintf (stderr, string); print_file_name (entry, stderr); fprintf (stderr, "\n"); + if (cplusplus) + unlink (ctor_and_dtor_filename); exit (1); } diff -cr2N bu.orig/ranlib.c bu/ranlib.c *** bu.orig/ranlib.c Sun Apr 23 02:16:23 1989 --- bu/ranlib.c Sun Apr 23 10:38:46 1989 *************** *** 3,10 **** #include - #include - #include #include void touch_symdefs (); --- 3,26 ---- #include #include + #include + #include + #include + #ifndef L_SET + #define L_SET 0 + #define L_INCR 1 + #endif + + #ifdef USG + #define bzero(s, n) (memset ((s), 0, (n))) + #define gettimeofday(TV,TZ) (time (TV)) + #define seconds(TV) TV + long time(); + #else + #define seconds(TV) TV.tv_sec + #include + #endif + void touch_symdefs (); *************** *** 47,52 **** --- 63,73 ---- char **largv; { + #ifdef USG + long tv; + #else struct timeval tv; struct timezone tz; + #endif + struct ar_hdr archive_header; int i, rr; *************** *** 82,86 **** sizeof (archive_header.ar_date)); ! sprintf (archive_header.ar_date, "%d", tv.tv_sec); for (i = 0; i < sizeof archive_header.ar_date; i++) --- 103,107 ---- sizeof (archive_header.ar_date)); ! sprintf (archive_header.ar_date, "%d", seconds (tv)); for (i = 0; i < sizeof archive_header.ar_date; i++) diff -cr2N bu.orig/robotussin.c bu/robotussin.c *** bu.orig/robotussin.c Sun Apr 23 02:16:24 1989 --- bu/robotussin.c Sun Apr 23 11:37:51 1989 *************** *** 44,48 **** --- 44,54 ---- /* Customization for a particular machine. */ + #ifdef i386 #define INPUT_MAGIC I386MAGIC + #else /* i386 */ + #if defined (m68k) || defined (mc68000) + #define INPUT_MAGIC MC68MAGIC + #endif + #endif /* i386 */ #include *************** *** 466,469 **** --- 472,481 ---- reloc_infop->r_length = 2; break; + #ifdef R_RELLONG + case R_RELLONG: + reloc_infop->r_pcrel = 0; + reloc_infop->r_length = 2; + break; + #endif default: error ("can't handle coff reloction type 0%o", coff_reloc.r_type);