Annotation of binutils/ld.c, revision 1.1

1.1     ! root        1: /* Linker `ld' for GNU
        !             2:    Copyright (C) 1988 Free Software Foundation, Inc.
        !             3: 
        !             4:                       NO WARRANTY
        !             5: 
        !             6:   BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
        !             7: NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
        !             8: WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
        !             9: RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
        !            10: WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
        !            11: BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
        !            12: FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
        !            13: AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE
        !            14: DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
        !            15: CORRECTION.
        !            16: 
        !            17:  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
        !            18: STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
        !            19: WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
        !            20: LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
        !            21: OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
        !            22: USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
        !            23: DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
        !            24: A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
        !            25: PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
        !            26: DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
        !            27: 
        !            28:                GENERAL PUBLIC LICENSE TO COPY
        !            29: 
        !            30:   1. You may copy and distribute verbatim copies of this source file
        !            31: as you receive it, in any medium, provided that you conspicuously
        !            32: and appropriately publish on each copy a valid copyright notice
        !            33: "Copyright (C) 1988 Free Software Foundation, Inc.", and include
        !            34: following the copyright notice a verbatim copy of the above disclaimer
        !            35: of warranty and of this License.
        !            36: 
        !            37:   2. You may modify your copy or copies of this source file or
        !            38: any portion of it, and copy and distribute such modifications under
        !            39: the terms of Paragraph 1 above, provided that you also do the following:
        !            40: 
        !            41:     a) cause the modified files to carry prominent notices stating
        !            42:     that you changed the files and the date of any change; and
        !            43: 
        !            44:     b) cause the whole of any work that you distribute or publish,
        !            45:     that in whole or in part contains or is a derivative of this
        !            46:     program or any part thereof, to be licensed at no charge to all
        !            47:     third parties on terms identical to those contained in this
        !            48:     License Agreement (except that you may choose to grant more extensive
        !            49:     warranty protection to some or all third parties, at your option).
        !            50: 
        !            51:     c) You may charge a distribution fee for the physical act of
        !            52:     transferring a copy, and you may at your option offer warranty
        !            53:     protection in exchange for a fee.
        !            54: 
        !            55: Mere aggregation of another unrelated program with this program (or its
        !            56: derivative) on a volume of a storage or distribution medium does not bring
        !            57: the other program under the scope of these terms.
        !            58: 
        !            59:   3. You may copy and distribute this program (or a portion or derivative
        !            60: of it, under Paragraph 2) in object code or executable form under the terms
        !            61: of Paragraphs 1 and 2 above provided that you also do one of the following:
        !            62: 
        !            63:     a) accompany it with the complete corresponding machine-readable
        !            64:     source code, which must be distributed under the terms of
        !            65:     Paragraphs 1 and 2 above; or,
        !            66: 
        !            67:     b) accompany it with a written offer, valid for at least three
        !            68:     years, to give any third party free (except for a nominal
        !            69:     shipping charge) a complete machine-readable copy of the
        !            70:     corresponding source code, to be distributed under the terms of
        !            71:     Paragraphs 1 and 2 above; or,
        !            72: 
        !            73:     c) accompany it with the information you received as to where the
        !            74:     corresponding source code may be obtained.  (This alternative is
        !            75:     allowed only for noncommercial distribution and only if you
        !            76:     received the program in object code or executable form alone.)
        !            77: 
        !            78: For an executable file, complete source code means all the source code for
        !            79: all modules it contains; but, as a special exception, it need not include
        !            80: source code for modules which are standard libraries that accompany the
        !            81: operating system on which the executable file runs.
        !            82: 
        !            83:   4. You may not copy, sublicense, distribute or transfer this program
        !            84: except as expressly provided under this License Agreement.  Any attempt
        !            85: otherwise to copy, sublicense, distribute or transfer this program is void and
        !            86: your rights to use the program under this License agreement shall be
        !            87: automatically terminated.  However, parties who have received computer
        !            88: software programs from you with this License Agreement will not have
        !            89: their licenses terminated so long as such parties remain in full compliance.
        !            90: 
        !            91:   5. If you wish to incorporate parts of this program into other free
        !            92: programs whose distribution conditions are different, write to the Free
        !            93: Software Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not yet
        !            94: worked out a simple rule that can be stated here, but we will often permit
        !            95: this.  We will be guided by the two goals of preserving the free status of
        !            96: all derivatives of our free software and of promoting the sharing and reuse of
        !            97: software.
        !            98: 
        !            99:  In other words, you are welcome to use, share and improve this program.
        !           100:  You are forbidden to forbid anyone else to use, share and improve
        !           101:  what you give them.   Help stamp out software-hoarding!  */
        !           102: 
        !           103: /* Written by Richard Stallman with some help from Eric Albert.  */
        !           104: 
        !           105: #include <a.out.h>
        !           106: #include <ar.h>
        !           107: #include <stdio.h>
        !           108: #include <sys/types.h>
        !           109: #include <strings.h>
        !           110: #include <sys/stat.h>
        !           111: #include "symseg.h"
        !           112: #include <sys/file.h>
        !           113: 
        !           114: #define min(a,b) ((a) < (b) ? (a) : (b))
        !           115: 
        !           116: /* Size of a page; obtained from the operating system.  */
        !           117: 
        !           118: int page_size;
        !           119: 
        !           120: /* System dependencies */
        !           121: 
        !           122: /* Define this if names etext, edata and end should not start with `_'.  */
        !           123: /* #define nounderscore 1 */
        !           124: 
        !           125: /* Define NON_NATIVE if using BSD or pseudo-BSD file format on a system
        !           126:    whose native format is different.  */
        !           127: /* #define NON_NATIVE */
        !           128: 
        !           129: /* Define this to specify the default executable format.  */
        !           130: 
        !           131: #ifdef hpux
        !           132: #define DEFAULT_MAGIC NMAGIC  /* hpux bugs screw ZMAGIC */
        !           133: #endif
        !           134: 
        !           135: #ifndef DEFAULT_MAGIC
        !           136: #define DEFAULT_MAGIC ZMAGIC
        !           137: #endif
        !           138: 
        !           139: /* Ordinary 4.3bsd lacks these macros in a.out.h.  */
        !           140: 
        !           141: #ifndef N_TXTADDR
        !           142: #ifdef vax
        !           143: #define N_TXTADDR(X) 0
        !           144: #endif
        !           145: #endif
        !           146: 
        !           147: #ifndef N_DATADDR
        !           148: #ifdef vax
        !           149: #define N_DATADDR(x) \
        !           150:        (((x).a_magic==OMAGIC)? (N_TXTADDR(x)+(x).a_text) \
        !           151:        : (page_size+((N_TXTADDR(x)+(x).a_text-1) & ~(page_size-1))))
        !           152: #endif
        !           153: #endif
        !           154: 
        !           155: #ifdef hpux
        !           156: #define getpagesize() EXEC_PAGESIZE
        !           157: #endif
        !           158: 
        !           159: /* Define how to initialize system-dependent header fields.  */
        !           160: #ifdef sun
        !           161: #define INITIALIZE_HEADER outheader.a_machtype = M_68020
        !           162: #endif
        !           163: #ifdef hpux
        !           164: #define INITIALIZE_HEADER outheader.a_machtype = HP9000S200_ID
        !           165: #endif
        !           166: 
        !           167: /* Symbol table */
        !           168: 
        !           169: /* Global symbol data is recorded in these structures,
        !           170:    one for each global symbol.
        !           171:    They are found via hashing in 'symtab', which points to a vector of buckets.
        !           172:    Each bucket is a chain of these structures through the link field.  */
        !           173: 
        !           174: typedef
        !           175:   struct glosym
        !           176:     {
        !           177:       /* Pointer to next symbol in this symbol's hash bucket.  */
        !           178:       struct glosym *link;
        !           179:       /* Name of this symbol.  */
        !           180:       char *name;
        !           181:       /* Value of this symbol as a global symbol.  */
        !           182:       long value;
        !           183:       /* Chain of external 'nlist's in files for this symbol, both defs and refs.  */
        !           184:       struct nlist *refs;
        !           185:       /* Nonzero means definitions of this symbol as common have been seen,
        !           186:         and the value here is the largest size specified by any of them.  */
        !           187:       int max_common_size;
        !           188:       /* For relocatable_output, records the index of this global sym in the
        !           189:         symbol table to be written, with the first global sym given index 0.  */
        !           190:       int def_count;
        !           191:       /* Nonzero means a definition of this global symbol is known to exist.
        !           192:         Library members should not be loaded on its account.  */
        !           193:       char defined;
        !           194:       /* Nonzero means a reference to this global symbol has been seen
        !           195:         in a file that is surely being loaded.
        !           196:         A value higher than 1 is the n_type code for the symbol's definition.  */
        !           197:       char referenced;
        !           198:       /* Nonzero means print a message at all refs or defs of this symbol */
        !           199:       char trace;
        !           200:     }
        !           201:   symbol;
        !           202: 
        !           203: /* Number of buckets in symbol hash table */
        !           204: #define        TABSIZE 1009
        !           205: 
        !           206: /* The symbol hash table: a vector of TABSIZE pointers to struct glosym. */
        !           207: symbol *symtab[TABSIZE];
        !           208: 
        !           209: /* Number of symbols in symbol hash table. */
        !           210: int num_hash_tab_syms = 0;
        !           211: 
        !           212: /* Count the number of nlist entries that are for local symbols.
        !           213:    This count and the three following counts
        !           214:    are incremented as as symbols are entered in the symbol table.  */
        !           215: int local_sym_count;
        !           216: 
        !           217: /* Count number of nlist entries that are for local symbols
        !           218:    whose names don't start with L. */
        !           219: int non_L_local_sym_count;
        !           220: 
        !           221: /* Count the number of nlist entries for debugger info.  */
        !           222: int debugger_sym_count;
        !           223: 
        !           224: /* Count the number of global symbols referenced and not defined.  */
        !           225: int undefined_global_sym_count;
        !           226: 
        !           227: /* Count the number of defined global symbols.
        !           228:    Each symbol is counted only once
        !           229:    regardless of how many different nlist entries refer to it,
        !           230:    since the output file will need only one nlist entry for it.
        !           231:    This count is computed by `digest_symbols';
        !           232:    it is undefined while symbols are being loaded. */
        !           233: int defined_global_sym_count;
        !           234: 
        !           235: /* Total number of symbols to be written in the output file.
        !           236:    Computed by digest_symbols from the variables above.  */
        !           237: int nsyms;
        !           238: 
        !           239: 
        !           240: /* Nonzero means ptr to symbol entry for symbol to use as start addr.
        !           241:    -e sets this.  */
        !           242: symbol *entry_symbol;
        !           243: 
        !           244: symbol *edata_symbol;   /* the symbol _edata */
        !           245: symbol *etext_symbol;   /* the symbol _etext */
        !           246: symbol *end_symbol;    /* the symbol _end */
        !           247: 
        !           248: /* Each input file, and each library member ("subfile") being loaded,
        !           249:    has a `file_entry' structure for it.
        !           250: 
        !           251:    For files specified by command args, these are contained in the vector
        !           252:    which `file_table' points to.
        !           253: 
        !           254:    For library members, they are dynamically allocated,
        !           255:    and chained through the `chain' field.
        !           256:    The chain is found in the `subfiles' field of the `file_entry'.
        !           257:    The `file_entry' objects for the members have `superfile' fields pointing
        !           258:    to the one for the library.  */
        !           259: 
        !           260: struct file_entry {
        !           261:   /* Name of this file.  */
        !           262:   char *filename;
        !           263:   /* Name to use for the symbol giving address of text start */
        !           264:   /* Usually the same as filename, but for a file spec'd with -l
        !           265:      this is the -l switch itself rather than the filename.  */
        !           266:   char *local_sym_name;
        !           267: 
        !           268:   /* Describe the layout of the contents of the file */
        !           269: 
        !           270:   /* The file's a.out header.  */
        !           271:   struct exec header;
        !           272:   /* Offset in file of GDB symbol segment, or 0 if there is none.  */
        !           273:   int symseg_offset;
        !           274: 
        !           275:   /* Describe data from the file loaded into core */
        !           276: 
        !           277:   /* Symbol table of the file.  */
        !           278:   struct nlist *symbols;
        !           279:   /* Size in bytes of string table.  */
        !           280:   int string_size;
        !           281:   /* Pointer to the string table.
        !           282:      The string table is not kept in core all the time,
        !           283:      but when it is in core, its address is here.  */
        !           284:   char *strings;
        !           285: 
        !           286:   /* Next two used only if `relocatable_output' */
        !           287: 
        !           288:   /* Text reloc info saved by `write_text' for `coptxtrel'.  */
        !           289:   struct relocation_info *textrel;
        !           290:   /* Data reloc info saved by `write_data' for `copdatrel'.  */
        !           291:   struct relocation_info *datarel;
        !           292: 
        !           293:   /* Relation of this file's segments to the output file */
        !           294: 
        !           295:   /* Start of this file's text seg in the output file core image.  */
        !           296:   int text_start_address;
        !           297:   /* Start of this file's data seg in the output file core image.  */
        !           298:   int data_start_address;
        !           299:   /* Start of this file's bss seg in the output file core image.  */
        !           300:   int bss_start_address;
        !           301:   /* Offset in bytes in the output file symbol table
        !           302:      of the first local symbol for this file.  Set by `write_file_symbols'.  */
        !           303:   int local_syms_offset;                                  
        !           304: 
        !           305:   /* For library members only */
        !           306: 
        !           307:   /* For a library, points to chain of entries for the library members.  */
        !           308:   struct file_entry *subfiles;
        !           309:   /* For a library member, offset of the member within the archive.
        !           310:      Zero for files that are not library members.  */
        !           311:   int starting_offset;
        !           312:   /* Size of contents of this file, if library member.  */
        !           313:   int total_size;
        !           314:   /* For library member, points to the library's own entry.  */
        !           315:   struct file_entry *superfile;
        !           316:   /* For library member, points to next entry for next member.  */
        !           317:   struct file_entry *chain;
        !           318: 
        !           319:   /* 1 if file is a library. */
        !           320:   char library_flag;
        !           321: 
        !           322:   /* 1 if file's header has been read into this structure.  */
        !           323:   char header_read_flag;
        !           324: 
        !           325:   /* 1 means search a set of directories for this file.  */
        !           326:   char search_dirs_flag;
        !           327: 
        !           328:   /* 1 means this is base file of incremental load.
        !           329:      Do not load this file's text or data.
        !           330:      Also default text_start to after this file's bss. */
        !           331:   char just_syms_flag;
        !           332: };
        !           333: 
        !           334: /* Vector of entries for input files specified by arguments.
        !           335:    These are all the input files except for members of specified libraries.  */
        !           336: struct file_entry *file_table;
        !           337: 
        !           338: /* Length of that vector.  */
        !           339: int number_of_files;
        !           340: 
        !           341: /* When loading the text and data, we can avoid doing a close
        !           342:    and another open between members of the same library.
        !           343: 
        !           344:    These two variables remember the file that is currently open.
        !           345:    Both are zero if no file is open.
        !           346: 
        !           347:    See `each_file' and `file_close'.  */
        !           348: 
        !           349: struct file_entry *input_file;
        !           350: int input_desc;
        !           351: 
        !           352: /* The name of the file to write; "a.out" by default.  */
        !           353: 
        !           354: char *output_filename;
        !           355: 
        !           356: /* Descriptor for writing that file with `mywrite'.  */
        !           357: 
        !           358: int outdesc;
        !           359: 
        !           360: /* Header for that file (filled in by `write_header').  */
        !           361: 
        !           362: struct exec outheader;
        !           363: 
        !           364: /* The following are computed by `digest_symbols'.  */
        !           365: 
        !           366: int text_size;         /* total size of text of all input files.  */
        !           367: int data_size;         /* total size of data of all input files.  */
        !           368: int bss_size;          /* total size of bss of all input files.  */
        !           369: int text_reloc_size;   /* total size of text relocation of all input files.  */
        !           370: int data_reloc_size;   /* total size of data relocation of all input files.  */
        !           371: 
        !           372: /* Amount of cleared space to leave between the text and data segments.  */
        !           373: 
        !           374: int text_pad;
        !           375: 
        !           376: /* Amount of bss segment to include as part of the data segment.  */
        !           377: 
        !           378: int data_pad;
        !           379: 
        !           380: /* Format of __.SYMDEF:
        !           381:    First, a longword containing the size of the 'symdef' data that follows.
        !           382:    Second, zero or more 'symdef' structures.
        !           383:    Third, a word containing the length of symbol name strings.
        !           384:    Fourth, zero or more symbol name strings (each followed by a zero).  */
        !           385: 
        !           386: struct symdef {
        !           387:   int symbol_name_string_index;
        !           388:   int library_member_offset;
        !           389: };
        !           390: 
        !           391: /* Record most of the command options.  */
        !           392: 
        !           393: /* Address we assume the text section will be loaded at.
        !           394:    We relocate symbols and text and data for this, but we do not
        !           395:    write any padding in the output file for it.  */
        !           396: int text_start;
        !           397: 
        !           398: /* Offset of default entry-pc within the text section.  */
        !           399: int entry_offset;
        !           400: 
        !           401: /* Address we decide the data section will be loaded at.  */
        !           402: int data_start;
        !           403: 
        !           404: /* `text-start' address is normally this much plus a page boundary.
        !           405:    This is not a user option; it is fixed for each system.  */
        !           406: int text_start_alignment;
        !           407: 
        !           408: /* Nonzero if -T was specified in the command line.
        !           409:    This prevents text_start from being set later to default values.  */
        !           410: int T_flag_specified;
        !           411: 
        !           412: /* Nonzero if -Tdata was specified in the command line.
        !           413:    This prevents data_start from being set later to default values.  */
        !           414: int Tdata_flag_specified;
        !           415: 
        !           416: /* Size to pad data section up to.
        !           417:    We simply increase the size of the data section, padding with zeros,
        !           418:    and reduce the size of the bss section to match.  */
        !           419: int specified_data_size;
        !           420: 
        !           421: /* Magic number to use for the output file, set by switch.  */
        !           422: int magic;
        !           423: 
        !           424: /* Nonzero means print names of input files as processed.  */
        !           425: int trace_files;
        !           426: 
        !           427: /* Which symbols should be stripped (omitted from the output):
        !           428:    none, all, or debugger symbols.  */
        !           429: enum { STRIP_NONE, STRIP_ALL, STRIP_DEBUGGER } strip_symbols;
        !           430: 
        !           431: /* Which local symbols should be omitted:
        !           432:    none, all, or those starting with L.
        !           433:    This is irrelevant if STRIP_NONE.  */
        !           434: enum { DISCARD_NONE, DISCARD_ALL, DISCARD_L } discard_locals;
        !           435: 
        !           436: /* 1 => write load map.  */
        !           437: int write_map;
        !           438: 
        !           439: /* 1 => write relocation into output file so can re-input it later.  */
        !           440: int relocatable_output;
        !           441: 
        !           442: /* 1 => assign space to common symbols even if `relocatable_output'.  */
        !           443: int force_common_definition;
        !           444: 
        !           445: /* Standard directories to search for files specified by -l.  */
        !           446: char *standard_search_dirs[] =
        !           447: #ifdef NON_NATIVE
        !           448:   {"/usr/local/lib/gnu"};
        !           449: #else
        !           450:   {"/lib", "/usr/lib", "/usr/local/lib"};
        !           451: #endif
        !           452: 
        !           453: /* Actual vector of directories to search;
        !           454:    this contains those specified with -L plus the standard ones.  */
        !           455: char **search_dirs;
        !           456: 
        !           457: /* Length of the vector `search_dirs'.  */
        !           458: int n_search_dirs;
        !           459: 
        !           460: /* Nonzero means should make the output file executable when done.  */
        !           461: /* Cleared by nonfatal errors.  */
        !           462: int make_executable;
        !           463: 
        !           464: void digest_symbols ();
        !           465: void print_symbols ();
        !           466: void load_symbols ();
        !           467: void decode_command ();
        !           468: void list_undefined_symbols ();
        !           469: void write_output ();
        !           470: void write_header ();
        !           471: void write_text ();
        !           472: void write_data ();
        !           473: void write_rel ();
        !           474: void write_syms ();
        !           475: void padfile ();
        !           476: char *concat ();
        !           477: symbol *getsym (), *getsym_soft ();
        !           478: 
        !           479: main (argc, argv)
        !           480:      char **argv;
        !           481:      int argc;
        !           482: {
        !           483:   page_size = getpagesize ();
        !           484: 
        !           485:   /* Clear the cumulative info on the output file.  */
        !           486: 
        !           487:   text_size = 0;
        !           488:   data_size = 0;
        !           489:   bss_size = 0;
        !           490:   text_reloc_size = 0;
        !           491:   data_reloc_size = 0;
        !           492: 
        !           493:   data_pad = 0;
        !           494:   text_pad = 0;
        !           495: 
        !           496:   /* Initialize the data about options.  */
        !           497: 
        !           498:   specified_data_size = 0;
        !           499:   strip_symbols = STRIP_NONE;
        !           500:   trace_files = 0;
        !           501:   discard_locals = DISCARD_NONE;
        !           502:   entry_symbol = 0;
        !           503:   write_map = 0;
        !           504:   relocatable_output = 0;
        !           505:   force_common_definition = 0;
        !           506:   T_flag_specified = 0;
        !           507:   Tdata_flag_specified = 0;
        !           508:   magic = DEFAULT_MAGIC;
        !           509:   make_executable = 1;
        !           510: 
        !           511:   /* Initialize the cumulative counts of symbols.  */
        !           512: 
        !           513:   local_sym_count = 0;
        !           514:   non_L_local_sym_count = 0;
        !           515:   debugger_sym_count = 0;
        !           516:   undefined_global_sym_count = 0;
        !           517: 
        !           518:   /* Completely decode ARGV.  */
        !           519: 
        !           520:   decode_command (argc, argv);
        !           521: 
        !           522:   /* Create the symbols `etext', `edata' and `end'.  */
        !           523: 
        !           524:   if (!relocatable_output)
        !           525:     symtab_init ();
        !           526: 
        !           527:   /* Determine whether to count the header as part of
        !           528:      the text size, and initialize the text size accordingly.
        !           529:      This depends on the kind of system and on the output format selected.  */
        !           530: 
        !           531:   outheader.a_magic = magic;
        !           532: #ifdef INITIALIZE_HEADER
        !           533:   INITIALIZE_HEADER;
        !           534: #endif
        !           535: 
        !           536:   text_size = sizeof (struct exec) - N_TXTOFF (outheader);
        !           537:   if (text_size < 0)
        !           538:     text_size = 0;
        !           539:   entry_offset = text_size;
        !           540: 
        !           541:   if (!T_flag_specified && !relocatable_output)
        !           542:     text_start = N_TXTADDR (outheader);
        !           543: 
        !           544:   /* The text-start address is normally this far past a page boundary.  */
        !           545:   text_start_alignment = text_start % page_size;
        !           546: 
        !           547:   /* Load symbols of all input files.
        !           548:      Also search all libraries and decide which library members to load.  */
        !           549: 
        !           550:   load_symbols ();
        !           551: 
        !           552:   /* Compute where each file's sections go, and relocate symbols.  */
        !           553: 
        !           554:   digest_symbols ();
        !           555: 
        !           556:   /* Print error messages for any missing symbols.  */
        !           557: 
        !           558:   if (!relocatable_output)
        !           559:     list_undefined_symbols (stderr);
        !           560: 
        !           561:   /* Print a map, if requested.  */
        !           562: 
        !           563:   if (write_map) print_symbols (stdout);
        !           564: 
        !           565:   /* Write the output file.  */
        !           566: 
        !           567:   write_output ();
        !           568: 
        !           569:   return 0;
        !           570: }
        !           571: 
        !           572: void decode_option ();
        !           573: 
        !           574: /* Analyze a command line argument.
        !           575:    Return 0 if the argument is a filename.
        !           576:    Return 1 if the argument is a option complete in itself.
        !           577:    Return 2 if the argument is a option which uses an argument.
        !           578: 
        !           579:    Thus, the value is the number of consecutive arguments
        !           580:    that are part of options.  */
        !           581: 
        !           582: int
        !           583: classify_arg (arg)
        !           584:      register char *arg;
        !           585: {
        !           586:   if (*arg != '-') return 0;
        !           587:   switch (arg[1])
        !           588:     {
        !           589:     case 'A':
        !           590:     case 'D':
        !           591:     case 'e':
        !           592:     case 'L':
        !           593:     case 'l':
        !           594:     case 'o':
        !           595:     case 'u':
        !           596:     case 'y':
        !           597:       if (arg[2])
        !           598:        return 1;
        !           599:       return 2;
        !           600: 
        !           601:     case 'T':
        !           602:       if (arg[2] == 0)
        !           603:        return 2;
        !           604:       if (! strcmp (&arg[2], "text"))
        !           605:        return 2;
        !           606:       if (! strcmp (&arg[2], "data"))
        !           607:        return 2;
        !           608:       return 1;
        !           609:     }
        !           610: 
        !           611:   return 1;
        !           612: }
        !           613: 
        !           614: /* Process the command arguments,
        !           615:    setting up file_table with an entry for each input file,
        !           616:    and setting variables according to the options.  */
        !           617: 
        !           618: void
        !           619: decode_command (argc, argv)
        !           620:      char **argv;
        !           621:      int argc;
        !           622: {
        !           623:   register int i;
        !           624:   register struct file_entry *p;
        !           625: 
        !           626:   number_of_files = 0;
        !           627:   output_filename = "a.out";
        !           628: 
        !           629:   n_search_dirs = 0;
        !           630:   search_dirs = (char **) xmalloc (sizeof (char *));
        !           631: 
        !           632:   /* First compute number_of_files so we know how long to make file_table.  */
        !           633:   /* Also process most options completely.  */
        !           634: 
        !           635:   for (i = 1; i < argc; i++)
        !           636:     {
        !           637:       register int code = classify_arg (argv[i]);
        !           638:       if (code)
        !           639:        {
        !           640:          if (i + code > argc)
        !           641:            fatal ("no argument following %s\n", argv[i]);
        !           642: 
        !           643:          decode_option (argv[i], argv[i+1]);
        !           644: 
        !           645:          if (argv[i][1] == 'l' || argv[i][1] == 'A')
        !           646:            number_of_files++;
        !           647: 
        !           648:          i += code - 1;
        !           649:        }
        !           650:       else
        !           651:        number_of_files++;
        !           652:     }
        !           653: 
        !           654:   if (!number_of_files)
        !           655:     fatal ("no input files", 0);
        !           656: 
        !           657:   p = file_table
        !           658:     = (struct file_entry *) xmalloc (number_of_files * sizeof (struct file_entry));
        !           659:   bzero (p, number_of_files * sizeof (struct file_entry));
        !           660: 
        !           661:   /* Now scan again and fill in file_table.  */
        !           662:   /* All options except -A and -l are ignored here.  */
        !           663: 
        !           664:   for (i = 1; i < argc; i++)
        !           665:     {
        !           666:       register int code = classify_arg (argv[i]);
        !           667: 
        !           668:       if (code)
        !           669:        {
        !           670:          char *string;
        !           671:          if (code == 2)
        !           672:            string = argv[i+1];
        !           673:          else
        !           674:            string = &argv[i][2];
        !           675: 
        !           676:          if (argv[i][1] == 'A')
        !           677:            {
        !           678:              if (p != file_table)
        !           679:                fatal ("-A specified before an input file other than the first");
        !           680: 
        !           681:              p->filename = string;
        !           682:              p->local_sym_name = string;
        !           683:              p->just_syms_flag = 1;
        !           684:              p++;
        !           685:            }
        !           686:          if (argv[i][1] == 'l')
        !           687:            {
        !           688:              p->filename = concat ("lib", string, ".a");
        !           689:              p->local_sym_name = concat ("-l", string, "");
        !           690:              p->search_dirs_flag = 1;
        !           691:              p++;
        !           692:            }
        !           693:          i += code - 1;
        !           694:        }
        !           695:       else
        !           696:        {
        !           697:          p->filename = argv[i];
        !           698:          p->local_sym_name = argv[i];
        !           699:          p++;
        !           700:        }
        !           701:     }
        !           702: 
        !           703:   /* Now check some option settings for consistency.  */
        !           704: 
        !           705:   if ((magic == ZMAGIC || magic == NMAGIC)
        !           706:       && (text_start - text_start_alignment) & (page_size - 1))
        !           707:     fatal ("-T argument not multiple of page size, with sharable output", 0);
        !           708: 
        !           709:   /* Append the standard search directories to the user-specified ones.  */
        !           710:   {
        !           711:     int n = sizeof standard_search_dirs / sizeof standard_search_dirs[0];
        !           712:     n_search_dirs += n;
        !           713:     search_dirs
        !           714:       = (char **) xrealloc (search_dirs, n_search_dirs * sizeof (char *));
        !           715:     bcopy (standard_search_dirs, &search_dirs[n_search_dirs - n],
        !           716:           n * sizeof (char *));
        !           717:   }
        !           718: }
        !           719: 
        !           720: /* Record an option and arrange to act on it later.
        !           721:    ARG should be the following command argument,
        !           722:    which may or may not be used by this option.
        !           723: 
        !           724:    The `l' and `A' options are ignored here since they actually
        !           725:    specify input files.  */
        !           726: 
        !           727: void
        !           728: decode_option (swt, arg)
        !           729:      register char *swt, *arg;
        !           730: {
        !           731:   if (! strcmp (swt, "Ttext"))
        !           732:     {
        !           733:       text_start = parse (arg, "%x", "invalid argument to -Ttext");
        !           734:       T_flag_specified = 1;
        !           735:       return;
        !           736:     }
        !           737:   if (! strcmp (swt, "Tdata"))
        !           738:     {
        !           739:       data_start = parse (arg, "%x", "invalid argument to -Tdata");
        !           740:       Tdata_flag_specified = 1;
        !           741:       return;
        !           742:     }
        !           743: 
        !           744:   if (swt[2] != 0)
        !           745:     arg = &swt[2];
        !           746: 
        !           747:   switch (swt[1])
        !           748:     {
        !           749:     case 'A':
        !           750:       return;
        !           751: 
        !           752:     case 'D':
        !           753:       specified_data_size = parse (arg, "%x", "invalid argument to -D");
        !           754:       return;
        !           755: 
        !           756:     case 'd':
        !           757:       force_common_definition = 1;
        !           758:       return;
        !           759: 
        !           760:     case 'e':
        !           761:       entry_symbol = getsym (arg);
        !           762:       if (!entry_symbol->defined && !entry_symbol->referenced)
        !           763:        undefined_global_sym_count++;
        !           764:       entry_symbol->referenced = 1;
        !           765:       return;
        !           766: 
        !           767:     case 'l':
        !           768:       return;
        !           769: 
        !           770:     case 'L':
        !           771:       n_search_dirs++;
        !           772:       search_dirs
        !           773:        = (char **) xrealloc (search_dirs, n_search_dirs * sizeof (char *));
        !           774:       search_dirs[n_search_dirs - 1] = arg;
        !           775:       return;
        !           776:       
        !           777:     case 'M':
        !           778:       write_map = 1;
        !           779:       return;
        !           780: 
        !           781:     case 'N':
        !           782:       magic = OMAGIC;
        !           783:       return;
        !           784: 
        !           785:     case 'n':
        !           786:       magic = NMAGIC;
        !           787:       return;
        !           788: 
        !           789:     case 'o':
        !           790:       output_filename = arg;
        !           791:       return;
        !           792: 
        !           793:     case 'r':
        !           794:       relocatable_output = 1;
        !           795:       magic = OMAGIC;
        !           796:       text_start = 0;
        !           797:       return;
        !           798: 
        !           799:     case 'S':
        !           800:       strip_symbols = STRIP_DEBUGGER;
        !           801:       return;
        !           802: 
        !           803:     case 's':
        !           804:       strip_symbols = STRIP_ALL;
        !           805:       return;
        !           806: 
        !           807:     case 'T':
        !           808:       text_start = parse (arg, "%x", "invalid argument to -T");
        !           809:       T_flag_specified = 1;
        !           810:       return;
        !           811: 
        !           812:     case 't':
        !           813:       trace_files = 1;
        !           814:       return;
        !           815: 
        !           816:     case 'u':
        !           817:       {
        !           818:        register symbol *sp = getsym (arg);
        !           819:        if (!sp->defined && !sp->referenced) undefined_global_sym_count++;
        !           820:        sp->referenced = 1;
        !           821:       }
        !           822:       return;
        !           823: 
        !           824:     case 'X':
        !           825:       discard_locals = DISCARD_L;
        !           826:       return;
        !           827: 
        !           828:     case 'x':
        !           829:       discard_locals = DISCARD_ALL;
        !           830:       return;
        !           831: 
        !           832:     case 'y':
        !           833:       {
        !           834:        register symbol *sp = getsym (&swt[2]);
        !           835:        sp->trace = 1;
        !           836:       }
        !           837:       return;
        !           838: 
        !           839:     case 'z':
        !           840:       magic = ZMAGIC;
        !           841:       return;
        !           842: 
        !           843:     default:
        !           844:       fatal ("invalid command option `%s'", swt);
        !           845:     }
        !           846: }
        !           847: 
        !           848: /** Convenient functions for operating on one or all files being loaded.  */
        !           849: 
        !           850: /* Call FUNCTION on each input file entry.
        !           851:    Do not call for entries for libraries;
        !           852:    instead, call once for each library member that is being loaded.
        !           853: 
        !           854:    FUNCTION receives two arguments: the entry, and ARG.  */
        !           855: 
        !           856: void
        !           857: each_file (function, arg)
        !           858:      register void (*function)();
        !           859:      register int arg;
        !           860: {
        !           861:   register int i;
        !           862: 
        !           863:   for (i = 0; i < number_of_files; i++)
        !           864:     {
        !           865:       register struct file_entry *entry = &file_table[i];
        !           866:       if (entry->library_flag)
        !           867:         {
        !           868:          register struct file_entry *subentry = entry->subfiles;
        !           869:          for (; subentry; subentry = subentry->chain)
        !           870:            (*function) (subentry, arg);
        !           871:        }
        !           872:       else
        !           873:        (*function) (entry, arg);
        !           874:     }
        !           875: }
        !           876: 
        !           877: /* Like `each_file' but ignore files that were just for symbol definitions.  */
        !           878: 
        !           879: void
        !           880: each_full_file (function, arg)
        !           881:      register void (*function)();
        !           882:      register int arg;
        !           883: {
        !           884:   register int i;
        !           885: 
        !           886:   for (i = 0; i < number_of_files; i++)
        !           887:     {
        !           888:       register struct file_entry *entry = &file_table[i];
        !           889:       if (entry->just_syms_flag)
        !           890:        continue;
        !           891:       if (entry->library_flag)
        !           892:         {
        !           893:          register struct file_entry *subentry = entry->subfiles;
        !           894:          for (; subentry; subentry = subentry->chain)
        !           895:            (*function) (subentry, arg);
        !           896:        }
        !           897:       else
        !           898:        (*function) (entry, arg);
        !           899:     }
        !           900: }
        !           901: 
        !           902: /* Close the input file that is now open.  */
        !           903: 
        !           904: void
        !           905: file_close ()
        !           906: {
        !           907:   close (input_desc);
        !           908:   input_desc = 0;
        !           909:   input_file = 0;
        !           910: }
        !           911: 
        !           912: /* Open the input file specified by 'entry', and return a descriptor.
        !           913:    The open file is remembered; if the same file is opened twice in a row,
        !           914:    a new open is not actually done.  */
        !           915: 
        !           916: int
        !           917: file_open (entry)
        !           918:      register struct file_entry *entry;
        !           919: {
        !           920:   register int desc;
        !           921: 
        !           922:   if (entry->superfile)
        !           923:     return file_open (entry->superfile);
        !           924: 
        !           925:   if (entry == input_file)
        !           926:     return input_desc;
        !           927: 
        !           928:   if (input_file) file_close ();
        !           929: 
        !           930:   if (entry->search_dirs_flag)
        !           931:     {
        !           932:       register char **p = search_dirs;
        !           933:       int i;
        !           934: 
        !           935:       for (i = 0; i < n_search_dirs; i++)
        !           936:        {
        !           937:          register char *string
        !           938:            = concat (search_dirs[i], "/", entry->filename);
        !           939:          desc = open (string, O_RDONLY, 0);
        !           940:          if (desc > 0)
        !           941:            {
        !           942:              entry->filename = string;
        !           943:              entry->search_dirs_flag = 0;
        !           944:              break;
        !           945:            }
        !           946:          free (string);
        !           947:        }
        !           948:     }
        !           949:   else
        !           950:     desc = open (entry->filename, O_RDONLY, 0);
        !           951: 
        !           952:   if (desc > 0)
        !           953:     {
        !           954:       input_file = entry;
        !           955:       input_desc = desc;
        !           956:       return desc;
        !           957:     }
        !           958: 
        !           959:   perror_file (entry);
        !           960: }
        !           961: 
        !           962: /* Print the filename of ENTRY on OUTFILE (a stdio stream),
        !           963:    and then a newline.  */
        !           964: 
        !           965: prline_file_name (entry, outfile)
        !           966:      struct file_entry *entry;
        !           967:      FILE *outfile;
        !           968: {
        !           969:   print_file_name (entry, outfile);
        !           970:   fprintf (outfile, "\n");
        !           971: }
        !           972: 
        !           973: /* Print the filename of ENTRY on OUTFILE (a stdio stream).  */
        !           974: 
        !           975: print_file_name (entry, outfile)
        !           976:      struct file_entry *entry;
        !           977:      FILE *outfile;
        !           978: {
        !           979:   if (entry->superfile)
        !           980:     {
        !           981:       print_file_name (entry->superfile, outfile);
        !           982:       fprintf (outfile, "(%s)", entry->filename);
        !           983:     }
        !           984:   else
        !           985:     fprintf (outfile, "%s", entry->filename);
        !           986: }
        !           987: 
        !           988: /* Medium-level input routines for rel files.  */
        !           989: 
        !           990: /* Read a file's header into the proper place in the file_entry.
        !           991:    DESC is the descriptor on which the file is open.
        !           992:    ENTRY is the file's entry.  */
        !           993: 
        !           994: void
        !           995: read_header (desc, entry)
        !           996:      int desc;
        !           997:      register struct file_entry *entry;
        !           998: {
        !           999:   register int len;
        !          1000:   struct exec *loc = &entry->header;
        !          1001: 
        !          1002:   lseek (desc, entry->starting_offset, 0);
        !          1003:   len = read (desc, loc, sizeof (struct exec));
        !          1004:   if (len != sizeof (struct exec))
        !          1005:     fatal_with_file ("failure reading header of ", entry);
        !          1006:   if (N_BADMAG (*loc))
        !          1007:     fatal_with_file ("bad magic number in ", entry);
        !          1008: 
        !          1009:   entry->header_read_flag = 1;
        !          1010: }
        !          1011: 
        !          1012: /* Read the symbols of file ENTRY into core.
        !          1013:    Assume it is already open, on descriptor DESC.
        !          1014:    Also read the length of the string table, which follows the symbol table,
        !          1015:    but don't read the contents of the string table.  */
        !          1016: 
        !          1017: void
        !          1018: read_entry_symbols (desc, entry)
        !          1019:      struct file_entry *entry;
        !          1020:      int desc;
        !          1021: {
        !          1022:   int str_size;
        !          1023: 
        !          1024:   if (!entry->header_read_flag)
        !          1025:     read_header (desc, entry);
        !          1026: 
        !          1027:   entry->symbols = (struct nlist *) xmalloc (entry->header.a_syms);
        !          1028: 
        !          1029:   lseek (desc, N_SYMOFF (entry->header) + entry->starting_offset, 0);
        !          1030:   if (entry->header.a_syms != read (desc, entry->symbols, entry->header.a_syms))
        !          1031:     fatal_with_file ("premature end of file in symbols of ", entry);
        !          1032: 
        !          1033:   lseek (desc, N_STROFF (entry->header) + entry->starting_offset, 0);
        !          1034:   if (sizeof str_size != read (desc, &str_size, sizeof str_size))
        !          1035:     fatal_with_file ("bad string table size in ", entry);
        !          1036: 
        !          1037:   entry->string_size = str_size;
        !          1038: }
        !          1039: 
        !          1040: /* Read the string table of file ENTRY into core.
        !          1041:    Assume it is already open, on descriptor DESC.
        !          1042:    Also record whether a GDB symbol segment follows the string table.  */
        !          1043: 
        !          1044: void
        !          1045: read_entry_strings (desc, entry)
        !          1046:      struct file_entry *entry;
        !          1047:      int desc;
        !          1048: {
        !          1049:   int buffer;
        !          1050: 
        !          1051:   if (!entry->header_read_flag)
        !          1052:     read_header (desc, entry);
        !          1053: 
        !          1054:   lseek (desc, N_STROFF (entry->header) + entry->starting_offset, 0);
        !          1055:   if (entry->string_size != read (desc, entry->strings, entry->string_size))
        !          1056:     fatal_with_file ("premature end of file in strings of ", entry);
        !          1057: 
        !          1058:   /* While we are here, see if the file has a symbol segment at the end.
        !          1059:      For a separate file, just try reading some more.
        !          1060:      For a library member, compare current pos against total size.  */
        !          1061:   if (entry->superfile)
        !          1062:     {
        !          1063:       if (entry->total_size == N_STROFF (entry->header) + entry->string_size)
        !          1064:        return;
        !          1065:     }
        !          1066:   else
        !          1067:     {
        !          1068:       buffer = read (desc, &buffer, sizeof buffer);
        !          1069:       if (buffer == 0)
        !          1070:        return;
        !          1071:       if (buffer != sizeof buffer)
        !          1072:        fatal_with_file ("premature end of file in GDB symbol segment of ", entry);
        !          1073:     }
        !          1074: 
        !          1075:   entry->symseg_offset = N_STROFF (entry->header) + entry->string_size;
        !          1076: }
        !          1077: 
        !          1078: /* Read in the symbols of all input files.  */
        !          1079: 
        !          1080: void read_file_symbols (), read_entry_symbols (), read_entry_strings ();
        !          1081: void enter_file_symbols (), enter_global_ref (), search_library ();
        !          1082: 
        !          1083: void
        !          1084: load_symbols ()
        !          1085: {
        !          1086:   register int i;
        !          1087: 
        !          1088:   if (trace_files) fprintf (stderr, "Loading symbols:\n\n");
        !          1089: 
        !          1090:   for (i = 0; i < number_of_files; i++)
        !          1091:     {
        !          1092:       register struct file_entry *entry = &file_table[i];
        !          1093:       read_file_symbols (entry);
        !          1094:     }
        !          1095: 
        !          1096:   if (trace_files) fprintf (stderr, "\n");
        !          1097: }
        !          1098: 
        !          1099: /* If ENTRY is a rel file, read its symbol and string sections into core.
        !          1100:    If it is a library, search it and load the appropriate members
        !          1101:    (which means calling this function recursively on those members).  */
        !          1102: 
        !          1103: void
        !          1104: read_file_symbols (entry)
        !          1105:      register struct file_entry *entry;
        !          1106: {
        !          1107:   register int desc;
        !          1108:   register int len;
        !          1109:   int magicnum;
        !          1110: 
        !          1111:   desc = file_open (entry);
        !          1112: 
        !          1113:   len = read (desc, &magicnum, sizeof magicnum);
        !          1114:   if (len != sizeof magicnum)
        !          1115:     fatal_with_file ("failure reading header of ", entry);
        !          1116: 
        !          1117:   if (!N_BADMAG (*((struct exec *)&magicnum)))
        !          1118:     {
        !          1119:       read_entry_symbols (desc, entry);
        !          1120:       entry->strings = (char *) alloca (entry->string_size);
        !          1121:       read_entry_strings (desc, entry);
        !          1122:       enter_file_symbols (entry);
        !          1123:       entry->strings = 0;
        !          1124:     }
        !          1125:   else
        !          1126:     {
        !          1127:       char armag[SARMAG];
        !          1128: 
        !          1129:       lseek (desc, 0, 0);
        !          1130:       if (SARMAG != read (desc, armag, SARMAG) || strncmp (armag, ARMAG, SARMAG))
        !          1131:        fatal_with_file ("malformed input file (not rel or archive) ", entry);
        !          1132:       entry->library_flag = 1;
        !          1133:       search_library (desc, entry);
        !          1134:     }
        !          1135: 
        !          1136:   file_close ();
        !          1137: }
        !          1138: 
        !          1139: /* Enter the external symbol defs and refs of ENTRY in the hash table.  */
        !          1140: 
        !          1141: void
        !          1142: enter_file_symbols (entry)
        !          1143:      struct file_entry *entry;
        !          1144: {
        !          1145:    register struct nlist *p, *end = entry->symbols + entry->header.a_syms / sizeof (struct nlist);
        !          1146: 
        !          1147:   if (trace_files) prline_file_name (entry, stderr);
        !          1148: 
        !          1149:   for (p = entry->symbols; p < end; p++)
        !          1150:     if (p->n_type & N_EXT)
        !          1151:       enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);
        !          1152:     else if (p->n_un.n_strx && !(p->n_type & (N_STAB | N_EXT)))
        !          1153:       {
        !          1154:        if ((p->n_un.n_strx + entry->strings)[0] != 'L')
        !          1155:          non_L_local_sym_count++;
        !          1156:        local_sym_count++;
        !          1157:       }
        !          1158:     else debugger_sym_count++;
        !          1159: 
        !          1160:    /* Count one for the local symbol that we generate,
        !          1161:       whose name is the file's name (usually) and whose address
        !          1162:       is the start of the file's text.  */
        !          1163: 
        !          1164:   local_sym_count++;
        !          1165:   non_L_local_sym_count++;
        !          1166: }
        !          1167: 
        !          1168: /* Enter one global symbol in the hash table.
        !          1169:    NLIST_P points to the `struct nlist' read from the file
        !          1170:    that describes the global symbol.  NAME is the symbol's name.
        !          1171:    ENTRY is the file entry for the file the symbol comes from.
        !          1172: 
        !          1173:    The `struct nlist' is modified by placing it on a chain of
        !          1174:    all such structs that refer to the same global symbol.
        !          1175:    This chain starts in the `refs' field of the symbol table entry
        !          1176:    and is chained through the `n_name'.  */
        !          1177: 
        !          1178: void
        !          1179: enter_global_ref (nlist_p, name, entry)
        !          1180:      register struct nlist *nlist_p;
        !          1181:      char *name;
        !          1182:      struct file_entry *entry;
        !          1183: {
        !          1184:   register symbol *sp = getsym (name);
        !          1185:   register int type = nlist_p->n_type;
        !          1186:   int oldref = sp->referenced;
        !          1187:   int olddef = sp->defined;
        !          1188: 
        !          1189:   nlist_p->n_un.n_name = (char *) sp->refs;
        !          1190:   sp->refs = nlist_p;
        !          1191: 
        !          1192:   sp->referenced = 1;
        !          1193: 
        !          1194:   if (type != (N_UNDF | N_EXT) || nlist_p->n_value)
        !          1195:     {
        !          1196:       sp->defined = 1;
        !          1197:       if (oldref && !olddef) undefined_global_sym_count--;
        !          1198:       /* If this is a common definition, keep track of largest
        !          1199:         common definition seen for this symbol.  */
        !          1200:       if (type == (N_UNDF | N_EXT)
        !          1201:          && sp->max_common_size < nlist_p->n_value)
        !          1202:        sp->max_common_size = nlist_p->n_value;
        !          1203:     }
        !          1204:   else
        !          1205:     if (!oldref) undefined_global_sym_count++;
        !          1206: 
        !          1207:   if (sp == end_symbol && entry->just_syms_flag && !T_flag_specified)
        !          1208:     text_start = nlist_p->n_value;
        !          1209: 
        !          1210:   if (sp->trace)
        !          1211:     {
        !          1212:       register char *reftype;
        !          1213:       switch (type & N_TYPE)
        !          1214:        {
        !          1215:        case N_UNDF:
        !          1216:          if (nlist_p->n_value)
        !          1217:            reftype = "defined as common";
        !          1218:          else reftype = "referenced";
        !          1219:          break;
        !          1220: 
        !          1221:        case N_ABS:
        !          1222:          reftype = "defined as absolute";
        !          1223:          break;
        !          1224: 
        !          1225:        case N_TEXT:
        !          1226:          reftype = "defined in text section";
        !          1227:          break;
        !          1228: 
        !          1229:        case N_DATA:
        !          1230:          reftype = "defined in data section";
        !          1231:          break;
        !          1232: 
        !          1233:        case N_BSS:
        !          1234:          reftype = "defined in BSS section";
        !          1235:          break;
        !          1236:        }
        !          1237: 
        !          1238:       fprintf (stderr, "symbol %s %s in ", sp->name, reftype);
        !          1239:       print_file_name (entry, stderr);
        !          1240:       fprintf (stderr, "\n");
        !          1241:     }
        !          1242: }
        !          1243: 
        !          1244: /* Searching libraries */
        !          1245: 
        !          1246: struct file_entry *decode_library_subfile ();
        !          1247: void linear_library (), symdef_library ();
        !          1248: 
        !          1249: /* Search the library ENTRY, already open on descriptor DESC.
        !          1250:    This means deciding which library members to load,
        !          1251:    making a chain of `struct file_entry' for those members,
        !          1252:    and entering their global symbols in the hash table.  */
        !          1253: 
        !          1254: void
        !          1255: search_library (desc, entry)
        !          1256:      int desc;
        !          1257:      struct file_entry *entry;
        !          1258: {
        !          1259:   int member_length;
        !          1260:   register char *name;
        !          1261:   register struct file_entry *subentry;
        !          1262: 
        !          1263:   if (!undefined_global_sym_count) return;
        !          1264: 
        !          1265:   /* Examine its first member, which starts SARMAG bytes in.  */
        !          1266:   subentry = decode_library_subfile (desc, entry, SARMAG, &member_length);
        !          1267:   if (!subentry) return;
        !          1268: 
        !          1269:   name = subentry->filename;
        !          1270:   free (subentry);
        !          1271: 
        !          1272:   /* Search via __.SYMDEF if that exists, else linearly.  */
        !          1273: 
        !          1274:   if (!strcmp (name, "__.SYMDEF"))
        !          1275:     symdef_library (desc, entry, member_length);
        !          1276:   else
        !          1277:     linear_library (desc, entry);
        !          1278: }
        !          1279: 
        !          1280: /* Construct and return a file_entry for a library member.
        !          1281:    The library's file_entry is library_entry, and the library is open on DESC.
        !          1282:    SUBFILE_OFFSET is the byte index in the library of this member's header.
        !          1283:    We store the length of the member into *LENGTH_LOC.  */
        !          1284: 
        !          1285: struct file_entry *
        !          1286: decode_library_subfile (desc, library_entry, subfile_offset, length_loc)
        !          1287:      int desc;
        !          1288:      struct file_entry *library_entry;
        !          1289:      int subfile_offset;
        !          1290:      int *length_loc;
        !          1291: {
        !          1292:   int bytes_read;
        !          1293:   register int namelen;
        !          1294:   int member_length;
        !          1295:   register char *name;
        !          1296:   struct ar_hdr hdr1;
        !          1297:   register struct file_entry *subentry;
        !          1298: 
        !          1299:   lseek (desc, subfile_offset, 0);
        !          1300: 
        !          1301:   bytes_read = read (desc, &hdr1, sizeof hdr1);
        !          1302:   if (!bytes_read)
        !          1303:     return 0;          /* end of archive */
        !          1304: 
        !          1305:   if (sizeof hdr1 != bytes_read)
        !          1306:     fatal_with_file ("malformed library archive ", library_entry);
        !          1307: 
        !          1308:   if (sscanf (hdr1.ar_size, "%d", &member_length) != 1)
        !          1309:     fatal_with_file ("malformatted header of archive member in ", library_entry);
        !          1310: 
        !          1311:   subentry = (struct file_entry *) xmalloc (sizeof (struct file_entry));
        !          1312:   bzero (subentry, sizeof (struct file_entry));
        !          1313: 
        !          1314:   for (namelen = 0;
        !          1315:        namelen < sizeof hdr1.ar_name
        !          1316:        && hdr1.ar_name[namelen] != 0 && hdr1.ar_name[namelen] != ' ';
        !          1317:        namelen++);
        !          1318: 
        !          1319:   name = (char *) xmalloc (namelen+1);
        !          1320:   strncpy (name, hdr1.ar_name, namelen);
        !          1321:   name[namelen] = 0;
        !          1322: 
        !          1323:   subentry->filename = name;
        !          1324:   subentry->local_sym_name = name;
        !          1325:   subentry->symbols = 0;
        !          1326:   subentry->strings = 0;
        !          1327:   subentry->subfiles = 0;
        !          1328:   subentry->starting_offset = subfile_offset + sizeof hdr1;
        !          1329:   subentry->superfile = library_entry;
        !          1330:   subentry->library_flag = 0;
        !          1331:   subentry->header_read_flag = 0;
        !          1332:   subentry->just_syms_flag = 0;
        !          1333:   subentry->chain = 0;
        !          1334:   subentry->total_size = member_length;
        !          1335: 
        !          1336:   (*length_loc) = member_length;
        !          1337: 
        !          1338:   return subentry;
        !          1339: }
        !          1340: 
        !          1341: /* Search a library that has a __.SYMDEF member.
        !          1342:    DESC is a descriptor on which the library is open.
        !          1343:      The file pointer is assumed to point at the __.SYMDEF data.
        !          1344:    ENTRY is the library's file_entry.
        !          1345:    MEMBER_LENGTH is the length of the __.SYMDEF data.  */
        !          1346: 
        !          1347: void
        !          1348: symdef_library (desc, entry, member_length)
        !          1349:      int desc;
        !          1350:      struct file_entry *entry;
        !          1351:      int member_length;
        !          1352: {
        !          1353:   int *symdef_data = (int *) xmalloc (member_length);
        !          1354:   register struct symdef *symdef_base;
        !          1355:   char *sym_name_base;
        !          1356:   int number_of_symdefs;
        !          1357:   int length_of_strings;
        !          1358:   int not_finished;
        !          1359:   int bytes_read;
        !          1360:   register int i;
        !          1361:   struct file_entry *prev = 0;
        !          1362:   int prev_offset = 0;
        !          1363: 
        !          1364:   bytes_read = read (desc, symdef_data, member_length);
        !          1365:   if (bytes_read != member_length)
        !          1366:     fatal_with_file ("malformatted __.SYMDEF in ", entry);
        !          1367: 
        !          1368:   number_of_symdefs = *symdef_data / sizeof (struct symdef);
        !          1369:   if (number_of_symdefs < 0 ||
        !          1370:        number_of_symdefs * sizeof (struct symdef) + 2 * sizeof (int) > member_length)
        !          1371:     fatal_with_file ("malformatted __.SYMDEF in ", entry);
        !          1372: 
        !          1373:   symdef_base = (struct symdef *) (symdef_data + 1);
        !          1374:   length_of_strings = *(int *) (symdef_base + number_of_symdefs);
        !          1375: 
        !          1376:   if (length_of_strings < 0
        !          1377:       || number_of_symdefs * sizeof (struct symdef) + length_of_strings
        !          1378:          + 2 * sizeof (int) != member_length)
        !          1379:     fatal_with_file ("malformatted __.SYMDEF in ", entry);
        !          1380: 
        !          1381:   sym_name_base = sizeof (int) + (char *) (symdef_base + number_of_symdefs);
        !          1382: 
        !          1383:   /* Check all the string indexes for validity.  */
        !          1384: 
        !          1385:   for (i = 0; i < number_of_symdefs; i++)
        !          1386:     {
        !          1387:       register int index = symdef_base[i].symbol_name_string_index;
        !          1388:       if (index < 0 || index >= length_of_strings
        !          1389:          || (index && *(sym_name_base + index - 1)))
        !          1390:        fatal_with_file ("malformatted __.SYMDEF in ", entry);
        !          1391:     }
        !          1392: 
        !          1393:   /* Search the symdef data for members to load.
        !          1394:      Do this until one whole pass finds nothing to load.  */
        !          1395: 
        !          1396:   not_finished = 1;
        !          1397:   while (not_finished)
        !          1398:     {
        !          1399:       not_finished = 0;
        !          1400: 
        !          1401:       /* Scan all the symbols mentioned in the symdef for ones that we need.
        !          1402:         Load the library members that contain such symbols.  */
        !          1403: 
        !          1404:       for (i = 0; i < number_of_symdefs && undefined_global_sym_count; i++)
        !          1405:        if (symdef_base[i].symbol_name_string_index >= 0)
        !          1406:          {
        !          1407:            register symbol *sp;
        !          1408: 
        !          1409:            sp = getsym_soft (sym_name_base
        !          1410:                              + symdef_base[i].symbol_name_string_index);
        !          1411: 
        !          1412:            /* If we find a symbol that appears to be needed, think carefully
        !          1413:               about the archive member that the symbol is in.  */
        !          1414: 
        !          1415:            if (sp && sp->referenced && !sp->defined)
        !          1416:              {
        !          1417:                int junk;
        !          1418:                register int j;
        !          1419:                register int offset = symdef_base[i].library_member_offset;
        !          1420:                struct file_entry *subentry;
        !          1421: 
        !          1422:                /* Don't think carefully about any archive member
        !          1423:                   more than once in a given pass.  */
        !          1424: 
        !          1425:                if (prev_offset == offset)
        !          1426:                  continue;
        !          1427:                prev_offset = offset;
        !          1428: 
        !          1429:                /* Read the symbol table of the archive member.  */
        !          1430: 
        !          1431:                subentry = decode_library_subfile (desc, entry, offset, &junk);
        !          1432:                read_entry_symbols (desc, subentry);
        !          1433:                subentry->strings = (char *) malloc (subentry->string_size);
        !          1434:                read_entry_strings (desc, subentry);
        !          1435: 
        !          1436:                /* Now scan the symbol table and decide whether to load.  */
        !          1437: 
        !          1438:                if (!subfile_wanted_p (subentry))
        !          1439:                  {
        !          1440:                    free (subentry->symbols);
        !          1441:                    free (subentry);
        !          1442:                  }
        !          1443:                else
        !          1444:                  {
        !          1445:                    /* This member is needed; load it.
        !          1446:                       Since we are loading something on this pass,
        !          1447:                       we must make another pass through the symdef data.  */
        !          1448: 
        !          1449:                    not_finished = 1;
        !          1450: 
        !          1451:                    enter_file_symbols (subentry);
        !          1452: 
        !          1453:                    if (prev)
        !          1454:                      prev->chain = subentry;
        !          1455:                    else entry->subfiles = subentry;
        !          1456:                    prev = subentry;
        !          1457: 
        !          1458:                    /* Clear out this member's symbols from the symdef data
        !          1459:                       so that following passes won't waste time on them.  */
        !          1460: 
        !          1461:                    for (j = 0; j < number_of_symdefs; j++)
        !          1462:                      {
        !          1463:                        if (symdef_base[j].library_member_offset == offset)
        !          1464:                          symdef_base[j].symbol_name_string_index = -1;
        !          1465:                      }
        !          1466:                  }
        !          1467: 
        !          1468:                /* We'll read the strings again if we need them again.  */
        !          1469:                free (subentry->strings);
        !          1470:              }
        !          1471:          }
        !          1472:     }
        !          1473: 
        !          1474:   free (symdef_data);
        !          1475: }
        !          1476: 
        !          1477: /* Search a library that has no __.SYMDEF.
        !          1478:    ENTRY is the library's file_entry.
        !          1479:    DESC is the descriptor it is open on.  */
        !          1480: 
        !          1481: void
        !          1482: linear_library (desc, entry)
        !          1483:      int desc;
        !          1484:      struct file_entry *entry;
        !          1485: {
        !          1486:   register struct file_entry *prev = 0;
        !          1487:   register int this_subfile_offset = SARMAG;
        !          1488: 
        !          1489:   while (undefined_global_sym_count)
        !          1490:     {
        !          1491:       int member_length;
        !          1492:       register struct file_entry *subentry;
        !          1493: 
        !          1494:       subentry = decode_library_subfile (desc, entry, this_subfile_offset, &member_length);
        !          1495: 
        !          1496:       if (!subentry) return;
        !          1497: 
        !          1498:       read_entry_symbols (desc, subentry);
        !          1499:       subentry->strings = (char *) alloca (subentry->string_size);
        !          1500:       read_entry_strings (desc, subentry);
        !          1501: 
        !          1502:       if (!subfile_wanted_p (subentry))
        !          1503:        {
        !          1504:          free (subentry->symbols);
        !          1505:          free (subentry);
        !          1506:        }
        !          1507:       else
        !          1508:        {
        !          1509:          enter_file_symbols (subentry);
        !          1510: 
        !          1511:          if (prev)
        !          1512:            prev->chain = subentry;
        !          1513:          else entry->subfiles = subentry;
        !          1514:          prev = subentry;
        !          1515:        }
        !          1516: 
        !          1517:       this_subfile_offset += member_length + sizeof (struct ar_hdr);
        !          1518:       if (this_subfile_offset & 1) this_subfile_offset++;
        !          1519:     }
        !          1520: }
        !          1521: 
        !          1522: /* ENTRY is an entry for a library member.
        !          1523:    Its symbols have been read into core, but not entered.
        !          1524:    Return nonzero if we ought to load this member.  */
        !          1525: 
        !          1526: int
        !          1527: subfile_wanted_p (entry)
        !          1528:      struct file_entry *entry;
        !          1529: {
        !          1530:   register struct nlist *p;
        !          1531:   register struct nlist *end
        !          1532:     = entry->symbols + entry->header.a_syms / sizeof (struct nlist);
        !          1533: 
        !          1534:   for (p = entry->symbols; p < end; p++)
        !          1535:     {
        !          1536:       register int type = p->n_type;
        !          1537: 
        !          1538:       if (type & N_EXT && (type != (N_UNDF | N_EXT) || p->n_value))
        !          1539:        {
        !          1540:          register char *name = p->n_un.n_strx + entry->strings;
        !          1541:          register symbol *sp = getsym_soft (name);
        !          1542: 
        !          1543:          /* If this symbol has not been hashed, we can't be looking for it. */
        !          1544: 
        !          1545:          if (!sp) continue;
        !          1546: 
        !          1547:          if (sp->referenced && !sp->defined)
        !          1548:            {
        !          1549:              /* This is a symbol we are looking for.  */
        !          1550:              if (type == (N_UNDF | N_EXT))
        !          1551:                {
        !          1552:                  /* Symbol being defined as common.
        !          1553:                     Remember this, but don't load subfile just for this.  */
        !          1554: 
        !          1555:                  if (sp->max_common_size < p->n_value)
        !          1556:                    sp->max_common_size = p->n_value;
        !          1557:                  if (!sp->defined)
        !          1558:                    undefined_global_sym_count--;
        !          1559:                  sp->defined = 1;
        !          1560:                  continue;
        !          1561:                }
        !          1562: 
        !          1563:              if (write_map)
        !          1564:                {
        !          1565:                  print_file_name (entry, stdout);
        !          1566:                  fprintf (stdout, " needed due to %s\n", sp->name);
        !          1567:                }
        !          1568:              return 1;
        !          1569:            }
        !          1570:        }
        !          1571:     }
        !          1572: 
        !          1573:   return 0;
        !          1574: }
        !          1575: 
        !          1576: void consider_file_section_lengths (), relocate_file_addresses ();
        !          1577: 
        !          1578: /* Having entered all the global symbols and found the sizes of sections
        !          1579:    of all files to be linked, make all appropriate deductions from this data.
        !          1580: 
        !          1581:    We propagate global symbol values from definitions to references.
        !          1582:    We compute the layout of the output file and where each input file's
        !          1583:    contents fit into it.  */
        !          1584: 
        !          1585: void
        !          1586: digest_symbols ()
        !          1587: {
        !          1588:   register int i;
        !          1589: 
        !          1590:   if (trace_files)
        !          1591:     fprintf (stderr, "Digesting symbol information:\n\n");
        !          1592: 
        !          1593:   /* Compute total size of sections */
        !          1594: 
        !          1595:   each_file (consider_file_section_lengths, 0);
        !          1596: 
        !          1597:   /* If necessary, pad text section to full page in the file.
        !          1598:      Include the padding in the text segment size.  */
        !          1599: 
        !          1600:   if (magic == NMAGIC || magic == ZMAGIC)
        !          1601:     {
        !          1602:       int text_end = text_size + N_TXTOFF (outheader);
        !          1603:       text_pad = ((text_end + page_size - 1) & (- page_size)) - text_end;
        !          1604:       text_size += text_pad;
        !          1605:     }
        !          1606: 
        !          1607:   outheader.a_text = text_size;
        !          1608: 
        !          1609:   /* Make the data segment address start in memory on a suitable boundary.  */
        !          1610: 
        !          1611:   if (! Tdata_flag_specified)
        !          1612:     data_start = N_DATADDR (outheader) + text_start - N_TXTADDR (outheader);
        !          1613: 
        !          1614:   /* Compute start addresses of each file's sections and symbols.  */
        !          1615: 
        !          1616:   each_full_file (relocate_file_addresses, 0);
        !          1617: 
        !          1618:   /* Now, for each symbol, verify that it is defined globally at most once.
        !          1619:      Put the global value into the symbol entry.
        !          1620:      Common symbols are allocated here, in the BSS section.
        !          1621:      Each defined symbol is given a '->defined' field
        !          1622:       which is the correct N_ code for its definition,
        !          1623:       except in the case of common symbols with -r.
        !          1624:      Then make all the references point at the symbol entry
        !          1625:      instead of being chained together. */
        !          1626: 
        !          1627:   defined_global_sym_count = 0;
        !          1628: 
        !          1629:   for (i = 0; i < TABSIZE; i++)
        !          1630:     {
        !          1631:       register symbol *sp;
        !          1632:       for (sp = symtab[i]; sp; sp = sp->link)
        !          1633:        {
        !          1634:          register struct nlist *p, *next;
        !          1635:          int defs = 0, com = sp->max_common_size, erred = 0;
        !          1636:          for (p = sp->refs; p; p = next)
        !          1637:            {
        !          1638:              register int type = p->n_type;
        !          1639:              if ((type & N_EXT) && type != (N_UNDF | N_EXT))
        !          1640:                {
        !          1641:                  /* non-common definition */
        !          1642:                  if (defs++ && sp->value != p->n_value)
        !          1643:                    if (!erred++)
        !          1644:                      {
        !          1645:                        make_executable = 0;
        !          1646:                        error ("multiple definitions of symbol %s", sp->name);
        !          1647:                      }
        !          1648:                  sp->value = p->n_value;
        !          1649:                  sp->defined = type;
        !          1650:                }
        !          1651:              next = (struct nlist *) p->n_un.n_name;
        !          1652:              p->n_un.n_name = (char *) sp;
        !          1653:            }
        !          1654:          /* Allocate as common if defined as common and not defined for real */
        !          1655:          if (com && !defs)
        !          1656:            {
        !          1657:              if (!relocatable_output || force_common_definition)
        !          1658:                {
        !          1659:                  com = (com + sizeof (int) - 1) & (- sizeof (int));
        !          1660:     
        !          1661:                  sp->value = data_start + data_size + bss_size;
        !          1662:                  sp->defined = N_BSS | N_EXT;
        !          1663:                  bss_size += com;
        !          1664:                  if (write_map)
        !          1665:                    printf ("Allocating common %s: %x at %x\n",
        !          1666:                            sp->name, com, sp->value);
        !          1667:                }
        !          1668:            }
        !          1669:          if (sp->defined)
        !          1670:            defined_global_sym_count++;
        !          1671:        }
        !          1672:     }
        !          1673: 
        !          1674:   if (end_symbol)              /* These are null if -r.  */
        !          1675:     {
        !          1676:       etext_symbol->value = text_size + text_start;
        !          1677:       edata_symbol->value = data_start + data_size;
        !          1678:       end_symbol->value = data_start + data_size + bss_size;
        !          1679:     }
        !          1680: 
        !          1681:   /* Figure the data_pad now, so that it overlaps with the bss addresses.  */
        !          1682: 
        !          1683:   if (specified_data_size && specified_data_size > data_size)
        !          1684:     data_pad = specified_data_size - data_size;
        !          1685: 
        !          1686:   if (magic == ZMAGIC)
        !          1687:     data_pad = ((data_pad + data_size + page_size - 1) & (- page_size))
        !          1688:                - data_size;
        !          1689: 
        !          1690:   bss_size -= data_pad;
        !          1691:   if (bss_size < 0) bss_size = 0;
        !          1692: 
        !          1693:   data_size += data_pad;
        !          1694: }
        !          1695: 
        !          1696: /* Accumulate the section sizes of input file ENTRY
        !          1697:    into the section sizes of the output file.  */
        !          1698: 
        !          1699: void
        !          1700: consider_file_section_lengths (entry)
        !          1701:      register struct file_entry *entry;
        !          1702: {
        !          1703:   if (entry->just_syms_flag)
        !          1704:     return;
        !          1705: 
        !          1706:   entry->text_start_address = text_size;
        !          1707:   text_size += entry->header.a_text;
        !          1708:   entry->data_start_address = data_size;
        !          1709:   data_size += entry->header.a_data;
        !          1710:   entry->bss_start_address = bss_size;
        !          1711:   bss_size += entry->header.a_bss;
        !          1712: 
        !          1713:   text_reloc_size += entry->header.a_trsize;
        !          1714:   data_reloc_size += entry->header.a_drsize;
        !          1715: }
        !          1716: 
        !          1717: /* Determine where the sections of ENTRY go into the output file,
        !          1718:    whose total section sizes are already known.
        !          1719:    Also relocate the addresses of the file's local and debugger symbols.  */
        !          1720: 
        !          1721: void
        !          1722: relocate_file_addresses (entry)
        !          1723:      register struct file_entry *entry;
        !          1724: {
        !          1725:   entry->text_start_address += text_start;
        !          1726:   /* Note that `data_start' and `data_size' have not yet been
        !          1727:      adjusted for `data_pad'.  If they had been, we would get the wrong
        !          1728:      results here.  */
        !          1729:   entry->data_start_address += data_start;
        !          1730:   entry->bss_start_address += data_start + data_size;
        !          1731: 
        !          1732:   {
        !          1733:     register struct nlist *p;
        !          1734:     register struct nlist *end
        !          1735:       = entry->symbols + entry->header.a_syms / sizeof (struct nlist);
        !          1736: 
        !          1737:     for (p = entry->symbols; p < end; p++)
        !          1738:       {
        !          1739:        /* If this belongs to a section, update it by the section's start address */
        !          1740:        register int type = p->n_type & N_TYPE;
        !          1741: 
        !          1742:        if (type == N_TEXT)
        !          1743:          p->n_value += entry->text_start_address;
        !          1744:        else if (type == N_DATA)
        !          1745:          /* A symbol whose value is in the data section
        !          1746:             is present in the input file as if the data section
        !          1747:             started at an address equal to the length of the file's text.  */
        !          1748:          p->n_value += entry->data_start_address - entry->header.a_text;
        !          1749:        else if (type == N_BSS)
        !          1750:          /* likewise for symbols with value in BSS.  */
        !          1751:          p->n_value += entry->bss_start_address
        !          1752:                         - entry->header.a_text - entry->header.a_data;
        !          1753:       }
        !          1754:   }
        !          1755: }
        !          1756: 
        !          1757: void describe_file_sections (), list_file_locals ();
        !          1758: 
        !          1759: /* Print a complete or partial map of the output file.  */
        !          1760: 
        !          1761: void
        !          1762: print_symbols (outfile)
        !          1763:      FILE *outfile;
        !          1764: {
        !          1765:   register int i;
        !          1766: 
        !          1767:   fprintf (outfile, "\nFiles:\n\n");
        !          1768: 
        !          1769:   each_file (describe_file_sections, outfile);
        !          1770: 
        !          1771:   fprintf (outfile, "\nGlobal symbols:\n\n");
        !          1772: 
        !          1773:   for (i = 0; i < TABSIZE; i++)
        !          1774:     {
        !          1775:       register symbol *sp;
        !          1776:       for (sp = symtab[i]; sp; sp = sp->link)
        !          1777:        {
        !          1778:          if (sp->defined == 1)
        !          1779:            fprintf (outfile, "  %s: common, length 0x%x\n", sp->name, sp->max_common_size);
        !          1780:          if (sp->defined)
        !          1781:            fprintf (outfile, "  %s: 0x%x\n", sp->name, sp->value);
        !          1782:          else if (sp->referenced)
        !          1783:            fprintf (outfile, "  %s: undefined\n", sp->name);
        !          1784:        }
        !          1785:     }
        !          1786: 
        !          1787:   each_file (list_file_locals, outfile);
        !          1788: }
        !          1789: 
        !          1790: void
        !          1791: describe_file_sections (entry, outfile)
        !          1792:      struct file_entry *entry;
        !          1793:      FILE *outfile;
        !          1794: {
        !          1795:   fprintf (outfile, "  ");
        !          1796:   print_file_name (entry, outfile);
        !          1797:   if (entry->just_syms_flag)
        !          1798:     fprintf (outfile, " symbols only\n", 0);
        !          1799:   else
        !          1800:     fprintf (outfile, " text %x(%x), data %x(%x), bss %x(%x) hex\n",
        !          1801:             entry->text_start_address, entry->header.a_text,
        !          1802:             entry->data_start_address, entry->header.a_data,
        !          1803:             entry->bss_start_address, entry->header.a_bss);
        !          1804: }
        !          1805: 
        !          1806: void
        !          1807: list_file_locals (entry, outfile)
        !          1808:      struct file_entry *entry;
        !          1809:      FILE *outfile;
        !          1810: {
        !          1811:   register struct nlist *p, *end = entry->symbols + entry->header.a_syms / sizeof (struct nlist);
        !          1812: 
        !          1813:   entry->strings = (char *) alloca (entry->string_size);
        !          1814:   read_entry_strings (file_open (entry), entry);
        !          1815: 
        !          1816:   fprintf (outfile, "\nLocal symbols of ");
        !          1817:   print_file_name (entry, outfile);
        !          1818:   fprintf (outfile, ":\n\n");
        !          1819: 
        !          1820:   for (p = entry->symbols; p < end; p++)
        !          1821:     /* If this is a definition, 
        !          1822:        update it if necessary by this file's start address.  */
        !          1823:     if (!(p->n_type & (N_STAB | N_EXT)))
        !          1824:       fprintf (outfile, "  %s: 0x%x\n",
        !          1825:               entry->strings + p->n_un.n_strx, p->n_value);
        !          1826: }
        !          1827: 
        !          1828: /* Print on OUTFILE a list of all the undefined global symbols.
        !          1829:    If there are any such, it is an error, so clear `make_executable'.  */
        !          1830: 
        !          1831: void
        !          1832: list_undefined_symbols (outfile)
        !          1833:      FILE *outfile;
        !          1834: {
        !          1835:   register int i;
        !          1836:   register int count = 0;
        !          1837: 
        !          1838:   for (i = 0; i < TABSIZE; i++)
        !          1839:     {
        !          1840:       register symbol *sp;
        !          1841:       for (sp = symtab[i]; sp; sp = sp->link)
        !          1842:        {
        !          1843:          if (sp->referenced && !sp->defined)
        !          1844:            {
        !          1845:              if (!count++)
        !          1846:                fprintf (outfile, "Undefined symbols:\n");
        !          1847:              fprintf (outfile, " %s\n", sp->name);
        !          1848:            }
        !          1849:        }
        !          1850:     }
        !          1851: 
        !          1852:   if (count)
        !          1853:     fprintf (outfile, "\n");
        !          1854:   if (count)
        !          1855:     make_executable = 0;
        !          1856: }
        !          1857: 
        !          1858: /* Write the output file */ 
        !          1859: 
        !          1860: void
        !          1861: write_output ()
        !          1862: {
        !          1863:   struct stat statbuf;
        !          1864:   int filemode;
        !          1865: 
        !          1866:   outdesc = open (output_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
        !          1867:   if (outdesc < 0) perror_name (output_filename);
        !          1868: 
        !          1869:   if (fstat (outdesc, &statbuf) < 0)
        !          1870:     perror_name (output_filename);
        !          1871: 
        !          1872:   filemode = statbuf.st_mode;
        !          1873: 
        !          1874:   chmod (output_filename, filemode & ~0111);
        !          1875: 
        !          1876:   /* Output the a.out header.  */
        !          1877:   write_header ();
        !          1878: 
        !          1879:   /* Output the text and data segments, relocating as we go.  */
        !          1880:   write_text ();
        !          1881:   write_data ();
        !          1882: 
        !          1883:   /* Output the merged relocation info, if requested with `-r'.  */
        !          1884:   if (relocatable_output)
        !          1885:     write_rel ();
        !          1886: 
        !          1887:   /* Output the symbol table (both globals and locals).  */
        !          1888:   write_syms ();
        !          1889: 
        !          1890:   /* Copy any GDB symbol segments from input files.  */
        !          1891:   write_symsegs ();
        !          1892: 
        !          1893:   close (outdesc);
        !          1894: 
        !          1895:   if (make_executable)
        !          1896:     chmod (output_filename, filemode | 0111);
        !          1897: }
        !          1898: 
        !          1899: void modify_location (), perform_relocation (), copy_text (), copy_data ();
        !          1900: 
        !          1901: void
        !          1902: write_header ()
        !          1903: {
        !          1904:   outheader.a_magic = magic;
        !          1905: #ifdef INITIALIZE_HEADER
        !          1906:   INITIALIZE_HEADER;
        !          1907: #endif
        !          1908:   outheader.a_text = text_size;
        !          1909:   outheader.a_data = data_size;
        !          1910:   outheader.a_bss = bss_size;
        !          1911:   outheader.a_entry = (entry_symbol ? entry_symbol->value
        !          1912:                       : text_start + entry_offset);
        !          1913: 
        !          1914:   if (strip_symbols == STRIP_ALL)
        !          1915:     nsyms = 0;
        !          1916:   else
        !          1917:     {
        !          1918:       nsyms = defined_global_sym_count + undefined_global_sym_count;
        !          1919:       if (discard_locals == DISCARD_L)
        !          1920:        nsyms += non_L_local_sym_count;
        !          1921:       else if (discard_locals == DISCARD_NONE)
        !          1922:        nsyms += local_sym_count;
        !          1923:     }
        !          1924: 
        !          1925:   if (strip_symbols == STRIP_NONE)
        !          1926:     nsyms += debugger_sym_count;
        !          1927: 
        !          1928:   outheader.a_syms = nsyms * sizeof (struct nlist);
        !          1929: 
        !          1930:   if (relocatable_output)
        !          1931:     {
        !          1932:       outheader.a_trsize = text_reloc_size;
        !          1933:       outheader.a_drsize = data_reloc_size;
        !          1934:     }
        !          1935:   else
        !          1936:     {
        !          1937:       outheader.a_trsize = 0;
        !          1938:       outheader.a_drsize = 0;
        !          1939:     }
        !          1940: 
        !          1941:   mywrite (&outheader, sizeof (struct exec), 1, outdesc);
        !          1942: 
        !          1943:   /* Output whatever padding is required in the executable file
        !          1944:      between the header and the start of the text.  */
        !          1945: 
        !          1946:   padfile (N_TXTOFF (outheader) - sizeof outheader, outdesc);
        !          1947: }
        !          1948: 
        !          1949: /* Relocate the text segment of each input file
        !          1950:    and write to the output file.  */
        !          1951: 
        !          1952: void
        !          1953: write_text ()
        !          1954: {
        !          1955:   if (trace_files)
        !          1956:     fprintf (stderr, "Copying and relocating text:\n\n");
        !          1957: 
        !          1958:   each_full_file (copy_text);
        !          1959:   file_close ();
        !          1960: 
        !          1961:   if (trace_files)
        !          1962:     fprintf (stderr, "\n");
        !          1963: 
        !          1964:   padfile (text_pad, outdesc);
        !          1965: }
        !          1966: 
        !          1967: int
        !          1968: text_offset (entry)
        !          1969:      struct file_entry *entry;
        !          1970: {
        !          1971:   return entry->starting_offset + N_TXTOFF (entry->header);
        !          1972: }
        !          1973: 
        !          1974: /* Read the text segment contents of ENTRY, relocate them,
        !          1975:    and write the result to the output file.
        !          1976:    If `-r', save the text relocation for later reuse.  */
        !          1977: 
        !          1978: void
        !          1979: copy_text (entry)
        !          1980:      struct file_entry *entry;
        !          1981: {
        !          1982:   register char *bytes;
        !          1983:   register int desc;
        !          1984:   register struct relocation_info *reloc;
        !          1985: 
        !          1986:   if (trace_files)
        !          1987:     prline_file_name (entry, stderr);
        !          1988: 
        !          1989:   desc = file_open (entry);
        !          1990: 
        !          1991:   /* Allocate space for the file's text section and text-relocation.  */
        !          1992: 
        !          1993:   bytes = (char *) alloca (entry->header.a_text);
        !          1994: 
        !          1995:   if (relocatable_output)
        !          1996:     reloc = (struct relocation_info *) xmalloc (entry->header.a_trsize);
        !          1997:   else
        !          1998:     reloc = (struct relocation_info *) alloca (entry->header.a_trsize);
        !          1999: 
        !          2000:   /* Read those two sections into core.  */
        !          2001: 
        !          2002:   lseek (desc, text_offset (entry), 0);
        !          2003:   if (entry->header.a_text != read (desc, bytes, entry->header.a_text))
        !          2004:     fatal_with_file ("premature eof in text section of ", entry);
        !          2005: 
        !          2006:   lseek (desc, text_offset (entry) + entry->header.a_text + entry->header.a_data, 0);
        !          2007:   if (entry->header.a_trsize != read (desc, reloc, entry->header.a_trsize))
        !          2008:     fatal_with_file ("premature eof in text relocation of ", entry);
        !          2009: 
        !          2010:   /* Relocate the text according to the text relocation.  */
        !          2011: 
        !          2012:   perform_relocation (bytes, entry->text_start_address, entry->header.a_text,
        !          2013:                      reloc, entry->header.a_trsize, entry);
        !          2014: 
        !          2015:   /* Write the relocated text to the output file.  */
        !          2016: 
        !          2017:   mywrite (bytes, 1, entry->header.a_text, outdesc);
        !          2018: 
        !          2019:   /* If `-r', record the text relocation permanently
        !          2020:      so the combined relocation can be written later.  */
        !          2021: 
        !          2022:   if (relocatable_output)
        !          2023:     entry->textrel = reloc;
        !          2024: }
        !          2025: 
        !          2026: /* Relocate the data segment of each input file
        !          2027:    and write to the output file.  */
        !          2028: 
        !          2029: void
        !          2030: write_data ()
        !          2031: {
        !          2032:   if (trace_files)
        !          2033:     fprintf (stderr, "Copying and relocating data:\n\n");
        !          2034: 
        !          2035:   each_full_file (copy_data);
        !          2036:   file_close ();
        !          2037: 
        !          2038:   if (trace_files)
        !          2039:     fprintf (stderr, "\n");
        !          2040: 
        !          2041:   padfile (data_pad, outdesc);
        !          2042: }
        !          2043: 
        !          2044: /* Read the data segment contents of ENTRY, relocate them,
        !          2045:    and write the result to the output file.
        !          2046:    If `-r', save the data relocation for later reuse.
        !          2047:    See comments in `copy_text'.  */
        !          2048: 
        !          2049: void
        !          2050: copy_data (entry)
        !          2051:      struct file_entry *entry;
        !          2052: {
        !          2053:   register struct relocation_info *reloc;
        !          2054:   register char *bytes;
        !          2055:   register int desc;
        !          2056: 
        !          2057:   if (trace_files)
        !          2058:     prline_file_name (entry, stderr);
        !          2059: 
        !          2060:   desc = file_open (entry);
        !          2061: 
        !          2062:   bytes = (char *) alloca (entry->header.a_data);
        !          2063: 
        !          2064:   if (relocatable_output)
        !          2065:     reloc = (struct relocation_info *) xmalloc (entry->header.a_drsize);
        !          2066:   else
        !          2067:     reloc = (struct relocation_info *) alloca (entry->header.a_drsize);
        !          2068: 
        !          2069:   lseek (desc, text_offset (entry) + entry->header.a_text, 0);
        !          2070:   if (entry->header.a_data != read (desc, bytes, entry->header.a_data))
        !          2071:     fatal_with_file ("premature eof in data section of ", entry);
        !          2072: 
        !          2073:   lseek (desc, text_offset (entry) + entry->header.a_text
        !          2074:                 + entry->header.a_data + entry->header.a_trsize,
        !          2075:               0);
        !          2076:   if (entry->header.a_drsize != read (desc, reloc, entry->header.a_drsize))
        !          2077:     fatal_with_file ("premature eof in data relocation of ", entry);
        !          2078: 
        !          2079:   perform_relocation (bytes, entry->data_start_address - entry->header.a_text,
        !          2080:                      entry->header.a_data, reloc, entry->header.a_drsize, entry);
        !          2081: 
        !          2082:   mywrite (bytes, 1, entry->header.a_data, outdesc);
        !          2083: 
        !          2084:   if (relocatable_output)
        !          2085:     entry->datarel = reloc;
        !          2086: }
        !          2087: 
        !          2088: /* Relocate ENTRY's text or data section contents.
        !          2089:    DATA is the address of the contents, in core.
        !          2090:    DATA_SIZE is the length of the contents.
        !          2091:    PC_RELOCATION is the difference between the address of the contents
        !          2092:      in the output file and its address in the input file.
        !          2093:    RELOC_INFO is the address of the relocation info, in core.
        !          2094:    RELOC_SIZE is its length in bytes.  */
        !          2095: 
        !          2096: void
        !          2097: perform_relocation (data, pc_relocation, data_size, reloc_info, reloc_size, entry)
        !          2098:      char *data;
        !          2099:      struct relocation_info *reloc_info;
        !          2100:      struct file_entry *entry;
        !          2101:      int pc_relocation;
        !          2102:      int data_size;
        !          2103:      int reloc_size;
        !          2104: {
        !          2105:   register struct relocation_info *p = reloc_info;
        !          2106:   struct relocation_info *end
        !          2107:     = reloc_info + reloc_size / sizeof (struct relocation_info);
        !          2108:   int text_relocation = entry->text_start_address;
        !          2109:   int data_relocation = entry->data_start_address - entry->header.a_text;
        !          2110:   int bss_relocation
        !          2111:     = entry->bss_start_address - entry->header.a_text - entry->header.a_data;
        !          2112: 
        !          2113:   for (; p < end; p++)
        !          2114:     {
        !          2115:       register int relocation = 0;
        !          2116:       register int addr = p->r_address;
        !          2117:       register int symbolnum = p->r_symbolnum;
        !          2118:       register int length = p->r_length;
        !          2119: 
        !          2120:       if (addr >= data_size)
        !          2121:        fatal_with_file ("relocation address out of range in ", entry);
        !          2122:       if (p->r_extern)
        !          2123:        {
        !          2124:          int symindex = symbolnum * sizeof (struct nlist);
        !          2125:          symbol *sp = ((symbol *)
        !          2126:                        (((struct nlist *)
        !          2127:                          (((char *)entry->symbols) + symindex))
        !          2128:                         ->n_un.n_name));
        !          2129: 
        !          2130:          if (symindex >= entry->header.a_syms)
        !          2131:            fatal_with_file ("relocation symbolnum out of range in ", entry);
        !          2132: 
        !          2133:          /* If the symbol is undefined, leave it at zero.  */
        !          2134:          if (! sp->defined)
        !          2135:            relocation = 0;
        !          2136:          else
        !          2137:            relocation = sp->value;
        !          2138:        }
        !          2139:       else switch (symbolnum)
        !          2140:        {
        !          2141:        case N_TEXT:
        !          2142:        case N_TEXT | N_EXT:
        !          2143:          relocation = text_relocation;
        !          2144:          break;
        !          2145: 
        !          2146:        case N_DATA:
        !          2147:        case N_DATA | N_EXT:
        !          2148:          /* A word that points to beginning of the the data section
        !          2149:             initially contains not 0 but rather the "address" of that section
        !          2150:             in the input file, which is the length of the file's text.  */
        !          2151:          relocation = data_relocation;
        !          2152:          break;
        !          2153: 
        !          2154:        case N_BSS:
        !          2155:        case N_BSS | N_EXT:
        !          2156:          /* Similarly, an input word pointing to the beginning of the bss
        !          2157:             initially contains the length of text plus data of the file.  */
        !          2158:          relocation = bss_relocation;
        !          2159:          break;
        !          2160: 
        !          2161:        case N_ABS:
        !          2162:        case N_ABS | N_EXT:
        !          2163:          /* Don't know why this code would occur, but apparently it does.  */
        !          2164:          break;
        !          2165: 
        !          2166:        default:
        !          2167:          fatal_with_file ("nonexternal relocation code invalid in ", entry);
        !          2168:        }
        !          2169: 
        !          2170:       if (p->r_pcrel)
        !          2171:        relocation -= pc_relocation;
        !          2172: 
        !          2173:       switch (length)
        !          2174:        {
        !          2175:        case 0:
        !          2176:          *(char *) (data + addr) += relocation;
        !          2177:          break;
        !          2178: 
        !          2179:        case 1:
        !          2180:          *(short *) (data + addr) += relocation;
        !          2181:          break;
        !          2182: 
        !          2183:        case 2:
        !          2184:          *(int *) (data + addr) += relocation;
        !          2185:          break;
        !          2186: 
        !          2187:        default:
        !          2188:          fatal_with_file ("invalid relocation field length in ", entry);
        !          2189:        }
        !          2190:     }
        !          2191: }
        !          2192: 
        !          2193: /* For relocatable_output only: write out the relocation,
        !          2194:    relocating the addresses-to-be-relocated.  */
        !          2195: 
        !          2196: void coptxtrel (), copdatrel ();
        !          2197: 
        !          2198: void
        !          2199: write_rel ()
        !          2200: {
        !          2201:   register int i;
        !          2202:   register int count = 0;
        !          2203: 
        !          2204:   if (trace_files)
        !          2205:     fprintf (stderr, "Writing text relocation:\n\n");
        !          2206: 
        !          2207:   /* Assign each global symbol a sequence number, giving the order
        !          2208:      in which `write_syms' will write it.
        !          2209:      This is so we can store the proper symbolnum fields
        !          2210:      in relocation entries we write.  */
        !          2211: 
        !          2212:   for (i = 0; i < TABSIZE; i++)
        !          2213:     {
        !          2214:       symbol *sp;
        !          2215:       for (sp = symtab[i]; sp; sp = sp->link)
        !          2216:        if (sp->referenced || sp->defined)
        !          2217:          sp->def_count = count++;
        !          2218:     }
        !          2219:   if (count != defined_global_sym_count + undefined_global_sym_count)
        !          2220:     fatal ("internal error");
        !          2221: 
        !          2222:   /* Write out the relocations of all files, remembered from copy_text.  */
        !          2223: 
        !          2224:   each_full_file (coptxtrel);
        !          2225: 
        !          2226:   if (trace_files)
        !          2227:     fprintf (stderr, "\nWriting data relocation:\n\n");
        !          2228: 
        !          2229:   each_full_file (copdatrel);
        !          2230: 
        !          2231:   if (trace_files)
        !          2232:     fprintf (stderr, "\n");
        !          2233: }
        !          2234: 
        !          2235: void
        !          2236: coptxtrel (entry)
        !          2237:      struct file_entry *entry;
        !          2238: {
        !          2239:   register struct relocation_info *p, *end;
        !          2240:   register int reloc = entry->text_start_address;
        !          2241: 
        !          2242:   p = entry->textrel;
        !          2243:   end = (struct relocation_info *) (entry->header.a_trsize + (char *) p);
        !          2244:   while (p < end)
        !          2245:     {
        !          2246:       p->r_address += reloc;
        !          2247:       if (p->r_extern)
        !          2248:        {
        !          2249:          register int symindex = p->r_symbolnum * sizeof (struct nlist);
        !          2250:          symbol *symptr = ((symbol *)
        !          2251:                            (((struct nlist *)
        !          2252:                              (((char *)entry->symbols) + symindex))
        !          2253:                             ->n_un.n_name));
        !          2254: 
        !          2255:          if (symindex >= entry->header.a_syms)
        !          2256:            fatal_with_file ("relocation symbolnum out of range in ", entry);
        !          2257:          /* If the symbol is now defined, change the external relocation
        !          2258:             to an internal one.  */
        !          2259:          if (symptr->defined)
        !          2260:            {
        !          2261:              p->r_extern = 0;
        !          2262:              p->r_symbolnum = (symptr->defined & N_TYPE);
        !          2263:            }
        !          2264:          else
        !          2265:            p->r_symbolnum = (symptr->def_count + nsyms
        !          2266:                              - defined_global_sym_count
        !          2267:                              - undefined_global_sym_count);
        !          2268:        }
        !          2269:       p++;
        !          2270:     }
        !          2271:   mywrite (entry->textrel, 1, entry->header.a_trsize, outdesc);
        !          2272: }
        !          2273: 
        !          2274: void
        !          2275: copdatrel (entry)
        !          2276:      struct file_entry *entry;
        !          2277: {
        !          2278:   register struct relocation_info *p, *end;
        !          2279:   /* Relocate the address of the relocation.
        !          2280:      Old address is relative to start of the input file's data section.
        !          2281:      New address is relative to start of the output file's data section.  */
        !          2282:   register int reloc = entry->data_start_address - text_size;
        !          2283: 
        !          2284:   p = entry->datarel;
        !          2285:   end = (struct relocation_info *) (entry->header.a_drsize + (char *) p);
        !          2286:   while (p < end)
        !          2287:     {
        !          2288:       p->r_address += reloc;
        !          2289:       if (p->r_extern)
        !          2290:        {
        !          2291:          register int symindex = p->r_symbolnum * sizeof (struct nlist);
        !          2292:          symbol *symptr = ((symbol *)
        !          2293:                            (((struct nlist *)
        !          2294:                              (((char *)entry->symbols) + symindex))
        !          2295:                             ->n_un.n_name));
        !          2296:          int symtype = symptr->defined & N_TYPE;
        !          2297: 
        !          2298:          if (symindex >= entry->header.a_syms)
        !          2299:            fatal_with_file ("relocation symbolnum out of range in ", entry);
        !          2300:          if (force_common_definition
        !          2301:              || symtype == N_DATA || symtype == N_TEXT || symtype == N_ABS)
        !          2302:            {
        !          2303:              p->r_extern = 0;
        !          2304:              p->r_symbolnum = symtype;
        !          2305:            }
        !          2306:          else
        !          2307:            p->r_symbolnum
        !          2308:              = (((symbol *)
        !          2309:                  (((struct nlist *)
        !          2310:                    (((char *)entry->symbols) + symindex))
        !          2311:                   ->n_un.n_name))
        !          2312:                 ->def_count
        !          2313:                 + nsyms - defined_global_sym_count
        !          2314:                 - undefined_global_sym_count);
        !          2315:        }
        !          2316:       p++;
        !          2317:     }
        !          2318:   mywrite (entry->datarel, 1, entry->header.a_drsize, outdesc);
        !          2319: }
        !          2320: 
        !          2321: void write_file_syms ();
        !          2322: void write_string_table ();
        !          2323: 
        !          2324: /* Offsets and current lengths of symbol and string tables in output file. */
        !          2325: 
        !          2326: int symbol_table_offset;
        !          2327: int symbol_table_len;
        !          2328: 
        !          2329: /* Address in output file where string table starts.  */
        !          2330: int string_table_offset;
        !          2331: 
        !          2332: /* Offset within string table
        !          2333:    where the strings in `strtab_vector' should be written.  */
        !          2334: int string_table_len;
        !          2335: 
        !          2336: /* Total size of string table strings allocated so far,
        !          2337:    including strings in `strtab_vector'.  */
        !          2338: int strtab_size;
        !          2339: 
        !          2340: /* Vector whose elements are strings to be added to the string table.  */
        !          2341: char **strtab_vector;
        !          2342: 
        !          2343: /* Vector whose elements are the lengths of those strings.  */
        !          2344: int *strtab_lens;
        !          2345: 
        !          2346: /* Index in `strtab_vector' at which the next string will be stored.  */
        !          2347: int strtab_index;
        !          2348: 
        !          2349: /* Add the string NAME to the output file string table.
        !          2350:    Record it in `strtab_vector' to be output later.
        !          2351:    Return the index within the string table that this string will have.  */
        !          2352: 
        !          2353: int
        !          2354: assign_string_table_index (name)
        !          2355:      char *name;
        !          2356: {
        !          2357:   register int index = strtab_size;
        !          2358:   register int len = strlen (name) + 1;
        !          2359: 
        !          2360:   strtab_size += len;
        !          2361:   strtab_vector[strtab_index] = name;
        !          2362:   strtab_lens[strtab_index++] = len;
        !          2363: 
        !          2364:   return index;
        !          2365: }
        !          2366: 
        !          2367: FILE *outstream = (FILE *) 0;
        !          2368: 
        !          2369: /* Write the contents of `strtab_vector' into the string table.
        !          2370:    This is done once for each file's local&debugger symbols
        !          2371:    and once for the global symbols.  */
        !          2372: 
        !          2373: void
        !          2374: write_string_table ()
        !          2375: {
        !          2376:   register int i;
        !          2377: 
        !          2378:   lseek (outdesc, string_table_offset + string_table_len, 0);
        !          2379: 
        !          2380:   if (!outstream)
        !          2381:     outstream = fdopen (outdesc, "w");
        !          2382: 
        !          2383:   for (i = 0; i < strtab_index; i++)
        !          2384:     {
        !          2385:       fwrite (strtab_vector[i], 1, strtab_lens[i], outstream);
        !          2386:       string_table_len += strtab_lens[i];
        !          2387:     }
        !          2388: 
        !          2389:   fflush (outstream);
        !          2390: 
        !          2391:   /* Report I/O error such as disk full.  */
        !          2392:   if (ferror (outstream))
        !          2393:     perror_name (output_filename);
        !          2394: }
        !          2395: 
        !          2396: /* Write the symbol table and string table of the output file.  */
        !          2397: 
        !          2398: void
        !          2399: write_syms ()
        !          2400: {
        !          2401:   /* Number of symbols written so far.  */
        !          2402:   int syms_written = 0;
        !          2403:   register int i;
        !          2404:   register symbol *sp;
        !          2405: 
        !          2406:   /* Buffer big enough for all the global symbols.  */
        !          2407:   struct nlist *buf
        !          2408:     = (struct nlist *) alloca ((defined_global_sym_count + undefined_global_sym_count)
        !          2409:                               * sizeof (struct nlist));
        !          2410:   /* Pointer for storing into BUF.  */
        !          2411:   register struct nlist *bufp = buf;
        !          2412: 
        !          2413:   /* Size of string table includes the bytes that store the size.  */
        !          2414:   strtab_size = sizeof strtab_size;
        !          2415: 
        !          2416:   symbol_table_offset = N_SYMOFF (outheader);
        !          2417:   symbol_table_len = 0;
        !          2418:   string_table_offset = N_STROFF (outheader);
        !          2419:   string_table_len = strtab_size;
        !          2420: 
        !          2421:   if (strip_symbols == STRIP_ALL)
        !          2422:     return;
        !          2423: 
        !          2424:   /* Write the local symbols defined by the various files.  */
        !          2425: 
        !          2426:   each_file (write_file_syms, &syms_written);
        !          2427:   file_close ();
        !          2428: 
        !          2429:   /* Now write out the global symbols.  */
        !          2430: 
        !          2431:   /* Allocate two vectors that record the data to generate the string
        !          2432:      table from the global symbols written so far.  */
        !          2433: 
        !          2434:   strtab_vector = (char **) alloca (num_hash_tab_syms * sizeof (char *));
        !          2435:   strtab_lens = (int *) alloca (num_hash_tab_syms * sizeof (int));
        !          2436:   strtab_index = 0;
        !          2437: 
        !          2438:   /* Scan the symbol hash table, bucket by bucket.  */
        !          2439: 
        !          2440:   for (i = 0; i < TABSIZE; i++)
        !          2441:     for (sp = symtab[i]; sp; sp = sp->link)
        !          2442:       {
        !          2443:        struct nlist nl;
        !          2444: 
        !          2445:        nl.n_other = 0;
        !          2446:        nl.n_desc = 0;
        !          2447: 
        !          2448:        /* Compute a `struct nlist' for the symbol.  */
        !          2449: 
        !          2450:        if (sp->defined || sp->referenced)
        !          2451:          {
        !          2452:            if (!sp->defined)         /* undefined -- legit only if -r */
        !          2453:              {
        !          2454:                nl.n_type = N_UNDF | N_EXT;
        !          2455:                nl.n_value = 0;
        !          2456:              }
        !          2457:            else if (sp->defined > 1) /* defined with known type */
        !          2458:              {
        !          2459:                nl.n_type = sp->defined;
        !          2460:                nl.n_value = sp->value;
        !          2461:              }
        !          2462:            else if (sp->max_common_size) /* defined as common but not allocated. */
        !          2463:              {
        !          2464:                /* happens only with -r and not -d */
        !          2465:                /* write out a common definition */
        !          2466:                nl.n_type = N_UNDF | N_EXT;
        !          2467:                nl.n_value = sp->max_common_size;
        !          2468:              }
        !          2469:            else
        !          2470:              fatal ("internal error: %s defined in mysterious way", sp->name);
        !          2471: 
        !          2472:            /* Allocate string table space for the symbol name.  */
        !          2473: 
        !          2474:            nl.n_un.n_strx = assign_string_table_index (sp->name);
        !          2475: 
        !          2476:            /* Output to the buffer and count it.  */
        !          2477: 
        !          2478:            *bufp++ = nl;
        !          2479:            syms_written++;
        !          2480:          }
        !          2481:       }
        !          2482: 
        !          2483:   /* Output the buffer full of `struct nlist's.  */
        !          2484: 
        !          2485:   lseek (outdesc, symbol_table_offset + symbol_table_len, 0);
        !          2486:   mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);
        !          2487:   symbol_table_len += sizeof (struct nlist) * (bufp - buf);
        !          2488: 
        !          2489:   if (syms_written != nsyms)
        !          2490:     fatal ("internal error: wrong number of symbols written into output file", 0);
        !          2491: 
        !          2492:   if (symbol_table_offset + symbol_table_len != string_table_offset)
        !          2493:     fatal ("internal error: inconsistent symbol table length", 0);
        !          2494: 
        !          2495:   /* Now the total string table size is known, so write it.
        !          2496:      We are already positioned at the right place in the file.  */
        !          2497: 
        !          2498:   mywrite (&strtab_size, sizeof (int), 1, outdesc);  /* we're at right place */
        !          2499: 
        !          2500:   /* Write the strings for the global symbols.  */
        !          2501: 
        !          2502:   write_string_table ();
        !          2503: }
        !          2504: 
        !          2505: /* Write the local and debugger symbols of file ENTRY.
        !          2506:    Increment *SYMS_WRITTEN_ADDR for each symbol that is written.  */
        !          2507: 
        !          2508: /* Note that we do not combine identical names of local symbols.
        !          2509:    dbx or gdb would be confused if we did that.  */
        !          2510: 
        !          2511: void
        !          2512: write_file_syms (entry, syms_written_addr)
        !          2513:      struct file_entry *entry;
        !          2514:      int *syms_written_addr;
        !          2515: {
        !          2516:   register struct nlist *p = entry->symbols;
        !          2517:   register struct nlist *end = p + entry->header.a_syms / sizeof (struct nlist);
        !          2518: 
        !          2519:   /* Buffer to accumulate all the syms before writing them.
        !          2520:      It has one extra slot for the local symbol we generate here.  */
        !          2521:   struct nlist *buf
        !          2522:     = (struct nlist *) alloca (entry->header.a_syms + sizeof (struct nlist));
        !          2523:   register struct nlist *bufp = buf;
        !          2524: 
        !          2525:   /* Upper bound on number of syms to be written here.  */
        !          2526:   int max_syms = (entry->header.a_syms / sizeof (struct nlist)) + 1;
        !          2527: 
        !          2528:   /* Make tables that record, for each symbol, its name and its name's length.
        !          2529:      The elements are filled in by `assign_string_table_index'.  */
        !          2530: 
        !          2531:   strtab_vector = (char **) alloca (max_syms * sizeof (char *));
        !          2532:   strtab_lens = (int *) alloca (max_syms * sizeof (int));
        !          2533:   strtab_index = 0;
        !          2534: 
        !          2535:   /* Generate a local symbol for the start of this file's text.  */
        !          2536: 
        !          2537:   if (discard_locals != DISCARD_ALL)
        !          2538:     {
        !          2539:       struct nlist nl;
        !          2540: 
        !          2541:       nl.n_type = N_TEXT;
        !          2542:       nl.n_un.n_strx = assign_string_table_index (entry->local_sym_name);
        !          2543:       nl.n_value = entry->text_start_address;
        !          2544:       nl.n_desc = 0;
        !          2545:       nl.n_other = 0;
        !          2546:       *bufp++ = nl;
        !          2547:       (*syms_written_addr)++;
        !          2548:       entry->local_syms_offset = *syms_written_addr * sizeof (struct nlist);
        !          2549:     }
        !          2550: 
        !          2551:   /* Read the file's string table.  */
        !          2552: 
        !          2553:   entry->strings = (char *) alloca (entry->string_size);
        !          2554:   read_entry_strings (file_open (entry), entry);
        !          2555: 
        !          2556:   for (; p < end; p++)
        !          2557:     {
        !          2558:       register int type = p->n_type;
        !          2559:       register int write = 0;
        !          2560: 
        !          2561:       /* WRITE gets 1 for a non-global symbol that should be written.  */
        !          2562: 
        !          2563:       if (!(type & (N_STAB | N_EXT)))
        !          2564:         /* ordinary local symbol */
        !          2565:        write = (discard_locals != DISCARD_ALL)
        !          2566:                && !(discard_locals == DISCARD_L &&
        !          2567:                     (p->n_un.n_strx + entry->strings)[0] == 'L');
        !          2568:       else if (!(type & N_EXT))
        !          2569:        /* debugger symbol */
        !          2570:         write = (strip_symbols == STRIP_NONE);
        !          2571: 
        !          2572:       if (write)
        !          2573:        {
        !          2574:          /* If this symbol has a name,
        !          2575:             allocate space for it in the output string table.  */
        !          2576: 
        !          2577:          if (p->n_un.n_strx)
        !          2578:            p->n_un.n_strx = assign_string_table_index (p->n_un.n_strx +
        !          2579:                                                        entry->strings);
        !          2580: 
        !          2581:          /* Output this symbol to the buffer and count it.  */
        !          2582: 
        !          2583:          *bufp++ = *p;
        !          2584:          (*syms_written_addr)++;
        !          2585:        }
        !          2586:     }
        !          2587: 
        !          2588:   /* All the symbols are now in BUF; write them.  */
        !          2589: 
        !          2590:   lseek (outdesc, symbol_table_offset + symbol_table_len, 0); 
        !          2591:   mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);
        !          2592:   symbol_table_len += sizeof (struct nlist) * (bufp - buf);
        !          2593: 
        !          2594:   /* Write the string-table data for the symbols just written,
        !          2595:      using the data in vectors `strtab_vector' and `strtab_lens'.  */
        !          2596: 
        !          2597:   write_string_table ();
        !          2598: }
        !          2599: 
        !          2600: /* Copy any GDB symbol segments from the input files to the output file.
        !          2601:    The contents of the symbol segment is copied without change
        !          2602:    except that we store some information into the beginning of it.  */
        !          2603: 
        !          2604: void write_file_symseg ();
        !          2605: 
        !          2606: write_symsegs ()
        !          2607: {
        !          2608:   each_file (write_file_symseg, 0);
        !          2609: }
        !          2610: 
        !          2611: void
        !          2612: write_file_symseg (entry)
        !          2613:      struct file_entry *entry;
        !          2614: {
        !          2615:   char buffer[4096];
        !          2616:   struct symbol_root root;
        !          2617:   int indesc;
        !          2618:   int len;
        !          2619: 
        !          2620:   if (entry->symseg_offset == 0)
        !          2621:     return;
        !          2622: 
        !          2623:   /* This entry has a symbol segment.  Read the root of the segment.  */
        !          2624: 
        !          2625:   indesc = file_open (entry);
        !          2626:   lseek (indesc, entry->symseg_offset + entry->starting_offset, 0);
        !          2627:   if (sizeof root != read (indesc, &root, sizeof root))
        !          2628:     fatal_with_file ("premature end of file in symbol segment of ", entry);
        !          2629: 
        !          2630:   /* Store some relocation info into the root.  */
        !          2631: 
        !          2632:   root.ldsymoff = entry->local_syms_offset;
        !          2633:   root.textrel = entry->text_start_address;
        !          2634:   root.datarel = entry->data_start_address - entry->header.a_text;
        !          2635:   root.bssrel = entry->bss_start_address
        !          2636:     - entry->header.a_text - entry->header.a_data;
        !          2637:   root.databeg = entry->data_start_address - root.datarel;
        !          2638:   root.bssbeg = entry->bss_start_address - root.bssrel;
        !          2639: 
        !          2640:   /* Write the modified root into the output file.  */
        !          2641: 
        !          2642:   mywrite (&root, sizeof root, 1, outdesc);
        !          2643: 
        !          2644:   /* Copy the rest of the symbol segment unchanged.  */
        !          2645: 
        !          2646:   if (entry->superfile)
        !          2647:     {
        !          2648:       /* Library member: number of bytes to copy is determined
        !          2649:         from the member's total size.  */
        !          2650: 
        !          2651:       int total = entry->total_size - entry->symseg_offset - sizeof root;
        !          2652: 
        !          2653:       while (total > 0)
        !          2654:        {
        !          2655:          len = read (indesc, buffer, min (sizeof buffer, total));
        !          2656: 
        !          2657:          if (len != min (sizeof buffer, total))
        !          2658:            fatal_with_file ("premature end of file in symbol segment of ", entry);
        !          2659:          total -= len;
        !          2660:          mywrite (buffer, len, 1, outdesc);
        !          2661:        }
        !          2662:     }
        !          2663:   else
        !          2664:     {
        !          2665:       /* A separate file: copy until end of file.  */
        !          2666: 
        !          2667:       while (len = read (indesc, buffer, sizeof buffer))
        !          2668:        {
        !          2669:          mywrite (buffer, len, 1, outdesc);
        !          2670:          if (len < sizeof buffer)
        !          2671:            break;
        !          2672:        }
        !          2673:     }
        !          2674: 
        !          2675:   file_close ();
        !          2676: }
        !          2677: 
        !          2678: /* Create the symbol table entries for `etext', `edata' and `end'.  */
        !          2679: 
        !          2680: symtab_init ()
        !          2681: {
        !          2682: #ifndef nounderscore
        !          2683:   edata_symbol = getsym ("_edata");
        !          2684:   etext_symbol = getsym ("_etext");
        !          2685:   end_symbol = getsym ("_end");
        !          2686: #else
        !          2687:   edata_symbol = getsym ("edata");
        !          2688:   etext_symbol = getsym ("etext");
        !          2689:   end_symbol = getsym ("end");
        !          2690: #endif
        !          2691: 
        !          2692:   edata_symbol->defined = N_DATA | N_EXT;
        !          2693:   etext_symbol->defined = N_TEXT | N_EXT;
        !          2694:   end_symbol->defined = N_BSS | N_EXT;
        !          2695: 
        !          2696:   edata_symbol->referenced = 1;
        !          2697:   etext_symbol->referenced = 1;
        !          2698:   end_symbol->referenced = 1;
        !          2699: }
        !          2700: 
        !          2701: /* Compute the hash code for symbol name KEY.  */
        !          2702: 
        !          2703: int
        !          2704: hash_string (key)
        !          2705:      char *key;
        !          2706: {
        !          2707:   register char *cp;
        !          2708:   register int k;
        !          2709: 
        !          2710:   cp = key;
        !          2711:   k = 0;
        !          2712:   while (*cp)
        !          2713:     k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
        !          2714: 
        !          2715:   return k;
        !          2716: }
        !          2717: 
        !          2718: /* Get the symbol table entry for the global symbol named KEY.
        !          2719:    Create one if there is none.  */
        !          2720: 
        !          2721: symbol *
        !          2722: getsym (key)
        !          2723:      char *key;
        !          2724: {
        !          2725:   register int hashval;
        !          2726:   register symbol *bp;
        !          2727: 
        !          2728:   /* Determine the proper bucket.  */
        !          2729: 
        !          2730:   hashval = hash_string (key) % TABSIZE;
        !          2731: 
        !          2732:   /* Search the bucket.  */
        !          2733: 
        !          2734:   for (bp = symtab[hashval]; bp; bp = bp->link)
        !          2735:     if (! strcmp (key, bp->name))
        !          2736:       return bp;
        !          2737: 
        !          2738:   /* Nothing was found; create a new symbol table entry.  */
        !          2739: 
        !          2740:   bp = (symbol *) xmalloc (sizeof (symbol));
        !          2741:   bp->refs = 0;
        !          2742:   bp->name = (char *) xmalloc (strlen (key) + 1);
        !          2743:   strcpy (bp->name, key);
        !          2744:   bp->defined = 0;
        !          2745:   bp->referenced = 0;
        !          2746:   bp->trace = 0;
        !          2747:   bp->value = 0;
        !          2748:   bp->max_common_size = 0;
        !          2749: 
        !          2750:   /* Add the entry to the bucket.  */
        !          2751: 
        !          2752:   bp->link = symtab[hashval];
        !          2753:   symtab[hashval] = bp;
        !          2754: 
        !          2755:   ++num_hash_tab_syms;
        !          2756: 
        !          2757:   return bp;
        !          2758: }
        !          2759: 
        !          2760: /* Like `getsym' but return 0 if the symbol is not already known.  */
        !          2761: 
        !          2762: symbol *
        !          2763: getsym_soft (key)
        !          2764:      char *key;
        !          2765: {
        !          2766:   register int hashval;
        !          2767:   register symbol *bp;
        !          2768: 
        !          2769:   /* Determine which bucket.  */
        !          2770: 
        !          2771:   hashval = hash_string (key) % TABSIZE;
        !          2772: 
        !          2773:   /* Search the bucket.  */
        !          2774: 
        !          2775:   for (bp = symtab[hashval]; bp; bp = bp->link)
        !          2776:     if (! strcmp (key, bp->name))
        !          2777:       return bp;
        !          2778: 
        !          2779:   return 0;
        !          2780: }
        !          2781: 
        !          2782: /* Report a fatal error.
        !          2783:    STRING is a printf format string and ARG is one arg for it.  */
        !          2784: 
        !          2785: fatal (string, arg)
        !          2786:      char *string, *arg;
        !          2787: {
        !          2788:   fprintf (stderr, "ld: ");
        !          2789:   fprintf (stderr, string, arg);
        !          2790:   fprintf (stderr, "\n");
        !          2791:   exit (1);
        !          2792: }
        !          2793: 
        !          2794: /* Report a fatal error.  The error message is STRING
        !          2795:    followed by the filename of ENTRY.  */
        !          2796: 
        !          2797: fatal_with_file (string, entry)
        !          2798:      char *string;
        !          2799:      struct file_entry *entry;
        !          2800: {
        !          2801:   fprintf (stderr, "ld: ");
        !          2802:   fprintf (stderr, string);
        !          2803:   print_file_name (entry, stderr);
        !          2804:   fprintf (stderr, "\n");
        !          2805:   exit (1);
        !          2806: }
        !          2807: 
        !          2808: /* Report a fatal error using the message for the last failed system call,
        !          2809:    followed by the string NAME.  */
        !          2810: 
        !          2811: perror_name (name)
        !          2812:      char *name;
        !          2813: {
        !          2814:   extern int errno, sys_nerr;
        !          2815:   extern char *sys_errlist[];
        !          2816:   char *s;
        !          2817: 
        !          2818:   if (errno < sys_nerr)
        !          2819:     s = concat ("", sys_errlist[errno], " for %s");
        !          2820:   else
        !          2821:     s = "cannot open %s";
        !          2822:   fatal (s, name);
        !          2823: }
        !          2824: 
        !          2825: /* Report a fatal error using the message for the last failed system call,
        !          2826:    followed by the name of file ENTRY.  */
        !          2827: 
        !          2828: perror_file (entry)
        !          2829:      struct file_entry *entry;
        !          2830: {
        !          2831:   extern int errno, sys_nerr;
        !          2832:   extern char *sys_errlist[];
        !          2833:   char *s;
        !          2834: 
        !          2835:   if (errno < sys_nerr)
        !          2836:     s = concat ("", sys_errlist[errno], " for ");
        !          2837:   else
        !          2838:     s = "cannot open ";
        !          2839:   fatal_with_file (s, entry);
        !          2840: }
        !          2841: 
        !          2842: /* Report a nonfatal error.
        !          2843:    STRING is a format for printf, and ARG1 ... ARG3 are args for it.  */
        !          2844: 
        !          2845: error (string, arg1, arg2, arg3)
        !          2846:      char *string, *arg1, *arg2, *arg3;
        !          2847: {
        !          2848:   fprintf (stderr, string, arg1, arg2, arg3);
        !          2849:   fprintf (stderr, "\n");
        !          2850: }
        !          2851: 
        !          2852: /* Output COUNT*ELTSIZE bytes of data at BUF
        !          2853:    to the descriptor DESC.  */
        !          2854: 
        !          2855: mywrite (buf, count, eltsize, desc)
        !          2856:      char *buf;
        !          2857:      int count;
        !          2858:      int eltsize;
        !          2859:      int desc;
        !          2860: {
        !          2861:   register int val;
        !          2862:   register int bytes = count * eltsize;
        !          2863: 
        !          2864:   while (bytes > 0)
        !          2865:     {
        !          2866:       val = write (desc, buf, bytes);
        !          2867:       if (val <= 0)
        !          2868:        perror_name (output_filename);
        !          2869:       buf += val;
        !          2870:       bytes -= val;
        !          2871:     }
        !          2872: }
        !          2873: 
        !          2874: /* Output PADDING zero-bytes to descriptor OUTDESC.
        !          2875:    PADDING may be negative; in that case, do nothing.  */
        !          2876: 
        !          2877: void
        !          2878: padfile (padding, outdesc)
        !          2879:      int padding;
        !          2880:      int outdesc;
        !          2881: {
        !          2882:   register char *buf;
        !          2883:   if (padding <= 0)
        !          2884:     return;
        !          2885: 
        !          2886:   buf = (char *) alloca (padding);
        !          2887:   bzero (buf, padding);
        !          2888:   mywrite (buf, padding, 1, outdesc);
        !          2889: }
        !          2890: 
        !          2891: /* Return a newly-allocated string
        !          2892:    whose contents concatenate the strings S1, S2, S3.  */
        !          2893: 
        !          2894: char *
        !          2895: concat (s1, s2, s3)
        !          2896:      char *s1, *s2, *s3;
        !          2897: {
        !          2898:   register int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
        !          2899:   register char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
        !          2900: 
        !          2901:   strcpy (result, s1);
        !          2902:   strcpy (result + len1, s2);
        !          2903:   strcpy (result + len1 + len2, s3);
        !          2904:   result[len1 + len2 + len3] = 0;
        !          2905: 
        !          2906:   return result;
        !          2907: }
        !          2908: 
        !          2909: /* Parse the string ARG using scanf format FORMAT, and return the result.
        !          2910:    If it does not parse, report fatal error
        !          2911:    generating the error message using format string ERROR and ARG as arg.  */
        !          2912: 
        !          2913: int
        !          2914: parse (arg, format, error)
        !          2915:      char *arg, *format;
        !          2916: {
        !          2917:   int x;
        !          2918:   if (1 != sscanf (arg, format, &x))
        !          2919:     fatal (error, arg);
        !          2920:   return x;
        !          2921: }
        !          2922: 
        !          2923: /* Like malloc but get fatal error if memory is exhausted.  */
        !          2924: 
        !          2925: int
        !          2926: xmalloc (size)
        !          2927:      int size;
        !          2928: {
        !          2929:   register int result = malloc (size);
        !          2930:   if (!result)
        !          2931:     fatal ("virtual memory exhausted", 0);
        !          2932:   return result;
        !          2933: }
        !          2934: 
        !          2935: /* Like realloc but get fatal error if memory is exhausted.  */
        !          2936: 
        !          2937: int
        !          2938: xrealloc (ptr, size)
        !          2939:      char *ptr;
        !          2940:      int size;
        !          2941: {
        !          2942:   register int result = realloc (ptr, size);
        !          2943:   if (!result)
        !          2944:     fatal ("virtual memory exhausted", 0);
        !          2945:   return result;
        !          2946: }

unix.superglobalmegacorp.com