Diff for /binutils/ld.c between versions 1.1.1.5 and 1.1.1.6

version 1.1.1.5, 2018/04/24 16:07:09 version 1.1.1.6, 2018/04/24 16:07:14
Line 23 Line 23
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <sys/file.h>  #include <sys/file.h>
   #ifndef USG
   #include <sys/time.h>
   #include <sys/resource.h>
   #endif
 #ifndef sony_news  #ifndef sony_news
 #include <fcntl.h>  #include <fcntl.h>
 #endif  #endif
   #ifdef ns32000
   struct relocation_info
   {  /* Look for the default declaration in a.out.gnu.h for documentation. */
     int r_address;
     unsigned int r_symbolnum:24;
     unsigned int r_pcrel:1;
     unsigned int r_length:2;
     unsigned int r_extern:1;
     unsigned int r_bsr:1;
     unsigned int r_disp:2;
     unsigned int r_pad:1;
   };
   #define N_RELOCATION_INFO_DECLARED
   #endif /*ns32000*/
   
   #if !defined(A_OUT) && !defined(MACH_O)
   #define A_OUT
   #endif
   
   #ifdef A_OUT
 #ifdef COFF_ENCAPSULATE  #ifdef COFF_ENCAPSULATE
 #include "a.out.encap.h"  #include "a.out.encap.h"
 #else  #else
 #include <a.out.h>  #include <a.out.h>
 #endif  #endif
   #endif
   
   #ifdef MACH_O
   #ifndef A_OUT
   #include <nlist.h>
   #include <reloc.h>
   #endif
   #ifndef N_TEXT
   #define N_TEXT 0x04
   #define N_DATA 0x06
   #define N_BSS 0x08
   #endif
   #include <sys/loader.h>
   #endif
   
 #ifndef N_SET_MAGIC  #ifndef N_SET_MAGIC
 #define N_SET_MAGIC(exec, val)  ((exec).a_magic = val)  #define N_SET_MAGIC(exec, val)  ((exec).a_magic = val)
Line 39 Line 76
   
 /* If compiled with GNU C, use the built-in alloca */  /* If compiled with GNU C, use the built-in alloca */
 #ifdef __GNUC__  #ifdef __GNUC__
 #define alloca __builtin_alloca  # define alloca __builtin_alloca
   #else
   # if defined(sun) && defined(sparc)
   #  include "alloca.h"
   # else
   char *alloca ();
   # endif
 #endif  #endif
   
   #include "getopt.h"
   
 /* Always use the GNU version of debugging symbol type codes, if possible.  */  /* Always use the GNU version of debugging symbol type codes, if possible.  */
   
 #include "stab.h"  #include "stab.h"
Line 86  char *progname; Line 131  char *progname;
 /* Define this to specify the default executable format.  */  /* Define this to specify the default executable format.  */
   
 #ifdef hpux  #ifdef hpux
 #define DEFAULT_MAGIC NMAGIC  /* hpux bugs screw ZMAGIC */  #define DEFAULT_OUTPUT_STYLE OUTPUT_READONLY_TEXT
 #endif  
   
 #ifndef DEFAULT_MAGIC  
 #define DEFAULT_MAGIC ZMAGIC  
 #endif  #endif
   
 /* Ordinary 4.3bsd lacks these macros in a.out.h.  */  /* Ordinary 4.3bsd lacks these macros in a.out.h.  */
   
 #ifndef N_TXTADDR  #ifndef N_TXTADDR
 #if defined(vax) || defined(sony_news)  #if defined(vax) || defined(sony_news) || defined(hp300) || defined(pyr)
 #define N_TXTADDR(X) 0  #define N_TXTADDR(X) 0
 #endif  #endif
 #ifdef is68k  #ifdef is68k
Line 105  char *progname; Line 146  char *progname;
 #ifdef sequent  #ifdef sequent
 #define N_TXTADDR(x) (N_ADDRADJ(x))  #define N_TXTADDR(x) (N_ADDRADJ(x))
 #endif  #endif
   #ifdef tek4300
   #define N_TXTADDR(x) ((x).a_magic == ZMAGIC ? page_size : 0)
   #endif
   #ifdef NeXT
   #define N_TXTADDR(X) ((X).a_magic == ZMAGIC ? page_size : 0)
   #endif
 #endif  #endif
   
 #ifndef N_DATADDR  #ifndef N_DATADDR
 #if defined(vax) || defined(sony_news)  #if defined(vax) || defined(sony_news) || defined(hp300) || defined(pyr)
 #define N_DATADDR(x) \  #define N_DATADDR(x) \
         (((x).a_magic==OMAGIC)? (N_TXTADDR(x)+(x).a_text) \          (((x).a_magic==OMAGIC)? (N_TXTADDR(x)+(x).a_text) \
         : (page_size+((N_TXTADDR(x)+(x).a_text-1) & ~(page_size-1))))          : (page_size+((N_TXTADDR(x)+(x).a_text-1) & ~(page_size-1))))
Line 124  char *progname; Line 171  char *progname;
         (((x).a_magic==OMAGIC)? (N_TXTADDR(x)+(x).a_text) \          (((x).a_magic==OMAGIC)? (N_TXTADDR(x)+(x).a_text) \
         : (page_size+(((x).a_text-1) & ~(page_size-1))))          : (page_size+(((x).a_text-1) & ~(page_size-1))))
 #endif  #endif
   #ifdef tek4300
   #define N_DATADDR(x) \
           (((x).a_magic==OMAGIC)? (N_TXTADDR(x)+(x).a_text) \
           : (page_size+((N_TXTADDR(x)+(x).a_text-1) & ~(page_size-1))))
   #endif
   #ifdef NeXT
   #define N_DATADDR(X) \
           (((X).a_magic==ZMAGIC)?(N_TXTADDR(X)+(X).a_text+0xFFFF)&~0xFFFF \
            :N_TXTADDR(X)+(X).a_text)
 #endif  #endif
   #endif
   
   /* The "address" of the data segment in a relocatable file.
      The text address of a relocatable file is always
      considered to be zero (instead of the value of N_TXTADDR, which
      is what the address is in an executable), so we need to subtract
      N_TXTADDR from N_DATADDR to get the "address" for the input file.  */
   #define DATA_ADDR_DOT_O(hdr) (N_DATADDR(hdr) - N_TXTADDR(hdr))
   
 /* Define how to initialize system-dependent header fields.  */  /* Define how to initialize system-dependent header fields.  */
 #ifdef sun  #ifdef sun
 #ifdef sparc  #ifdef sparc
 #define INITIALIZE_HEADER \  #define INITIALIZE_HEADER \
   {outheader.a_machtype = M_SPARC; outheader.a_toolversion = 1;}    {outheader.a_machtype = M_SPARC; outheader.a_toolversion = 1;}
 #endif  #endif /* sparc.  */
 #if defined(mc68010) || defined(m68010)  #if defined(mc68000)
 #define INITIALIZE_HEADER outheader.a_machtype = M_68010  /* Set the machine type according to the machine type of the .o files.
 #endif     If they are all sun2 (68010), then the type of the executable is sun2.
 #ifndef INITIALIZE_HEADER     If any is sun3 (68020), then the type of the executable is sun3.
 #define INITIALIZE_HEADER outheader.a_machtype = M_68020     This is consistent with the Sun loader and more useful than having
 #endif     it depend on which machine you are on when you run ld.  */
 #endif  static int sun_machtype = M_68010;
   #define INITIALIZE_HEADER outheader.a_machtype = sun_machtype
   #define READ_HEADER_HOOK(machtype) \
     if (machtype == M_68020)           \
       {                                \
         sun_machtype = M_68020;        \
       }
   #endif /* mc68000.  */
   #endif /* Sun.  */
   
 #ifdef ALTOS  #ifdef ALTOS
 #define INITIALIZE_HEADER N_SET_MACHTYPE (outheader, M_68020)  #define INITIALIZE_HEADER N_SET_MACHTYPE (outheader, M_68020)
 #endif  #endif
Line 155  char *progname; Line 228  char *progname;
 #endif  #endif
 #if defined(i386) && !defined(sequent)  #if defined(i386) && !defined(sequent)
 #define INITIALIZE_HEADER N_SET_MACHTYPE (outheader, M_386)  #define INITIALIZE_HEADER N_SET_MACHTYPE (outheader, M_386)
   #endif /* Sequent symmetry.  */
   #if defined(hp300)
   #define INITIALIZE_HEADER outheader.a_mid = MID_HP300
   /* MORE/bsd tags the filename symbol with N_FN|N_EXT not N_TEXT */
   #define OFILE_FN_FLAGGED
   #endif /* hp300.  */
   #ifdef pyr
   #define INITIALIZE_HEADER outheader.a_machid = PYR90X
   #endif /* Pyramid.  */
   
   #ifdef tek4300
   #undef INITIALIZE_HEADER
   #define INITIALIZE_HEADER (outheader).a_archclass = ARCHCLASS_MC68020, (outheader).a_textoff = ZMOFF
   /* The alternative to the following patch is to change field "header"
      in struct file_entry, from struct exec to struct zexec; this affects
      the -A option */
   #undef N_DATOFF
   #define N_DATOFF(x) ( (x).a_magic==ZMAGIC               \
                        ? (ZMOFF + (x).a_text)             \
                        : (sizeof (struct exec) + (x).a_text) )
 #endif  #endif
   
 #ifdef is68k  #ifdef is68k
Line 164  char *progname; Line 257  char *progname;
 #define DOLLAR_KLUDGE  #define DOLLAR_KLUDGE
 #endif  #endif
   
 /*  /* Values for 3rd argument to lseek().  */
  * Alloca include.  
  */  
 #if defined(sun) && defined(sparc) && !defined(__GNUC__)  
 #include "alloca.h"  
 #endif  
   
 #ifndef L_SET  #ifndef L_SET
 #define L_SET 0  #define L_SET 0
 #endif  #endif
   /* This is called L_INCR in BSD, but SEEK_CUR in POSIX.  */
   #ifndef SEEK_CUR
   #define SEEK_CUR 1
   #endif
   
 /*  /*
  * Ok.  Following are the relocation information macros.  If your   * Ok.  Following are the relocation information macros.  If your
Line 193  char *progname; Line 284  char *progname;
  * what the value of the relocation actually was.  *Must be an lvalue*.   * what the value of the relocation actually was.  *Must be an lvalue*.
  *   *
  *   RELOC_TYPE (rval): For a non-external relocation, this is the   *   RELOC_TYPE (rval): For a non-external relocation, this is the
  * segment to relocate for.   * segment to relocate for.  *Must be an lvalue.*
  *   *
  *   RELOC_SYMBOL (rval): For an external relocation, this is the   *   RELOC_SYMBOL (rval): For an external relocation, this is the
  * index of its symbol in the symbol table.  *Must be an lvalue*.   * index of its symbol in the symbol table.  *Must be an lvalue*.
Line 257  char *progname; Line 348  char *progname;
 /* Sparc (Sun 4) macros */  /* Sparc (Sun 4) macros */
 #undef relocation_info  #undef relocation_info
 #define relocation_info                 reloc_info_sparc  #define relocation_info                 reloc_info_sparc
 #define RELOC_ADDRESS(r)                ((r)->r_address)                   #define RELOC_ADDRESS(r)                ((r)->r_address)
 #define RELOC_EXTERN_P(r)               ((r)->r_extern)        #define RELOC_EXTERN_P(r)               ((r)->r_extern)
 #define RELOC_TYPE(r)                   ((r)->r_index)    #define RELOC_TYPE(r)                   ((r)->r_index)
 #define RELOC_SYMBOL(r)                 ((r)->r_index)     #define RELOC_SYMBOL(r)                 ((r)->r_index)
 #define RELOC_MEMORY_SUB_P(r)           0  #define RELOC_MEMORY_SUB_P(r)           0
 #define RELOC_MEMORY_ADD_P(r)           0  #define RELOC_MEMORY_ADD_P(r)           0
 #define RELOC_ADD_EXTRA(r)              ((r)->r_addend)         #define RELOC_ADD_EXTRA(r)              ((r)->r_addend)
 #define RELOC_PCREL_P(r)             \  #define RELOC_PCREL_P(r)             \
         ((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22)          ((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22)
 #define RELOC_VALUE_RIGHTSHIFT(r)       (reloc_target_rightshift[(r)->r_type])  #define RELOC_VALUE_RIGHTSHIFT(r)       (reloc_target_rightshift[(r)->r_type])
Line 288  static int reloc_target_bitsize[] = { Line 379  static int reloc_target_bitsize[] = {
 #define MAX_ALIGNMENT   (sizeof (double))  #define MAX_ALIGNMENT   (sizeof (double))
 #endif  #endif
   
 #ifdef sequent  #if defined(sequent) || defined(ns32000)
 #define RELOC_ADDRESS(r)                ((r)->r_address)  #define RELOC_ADDRESS(r)                ((r)->r_address)
 #define RELOC_EXTERN_P(r)               ((r)->r_extern)  #define RELOC_EXTERN_P(r)               ((r)->r_extern)
 #define RELOC_TYPE(r)           ((r)->r_symbolnum)  #define RELOC_TYPE(r)           ((r)->r_symbolnum)
 #define RELOC_SYMBOL(r)         ((r)->r_symbolnum)  #define RELOC_SYMBOL(r)         ((r)->r_symbolnum)
   #ifdef sequent                  /* I think r_bsr is needed only for compat.
                                      with sequent object files, or that's
                                      what Ian has done.  But might be that
                                      this is needed for all 32k machines.*/
 #define RELOC_MEMORY_SUB_P(r)   ((r)->r_bsr)  #define RELOC_MEMORY_SUB_P(r)   ((r)->r_bsr)
   #else
   #define RELOC_MEMORY_SUB_P(r) 0
   #endif
 #define RELOC_MEMORY_ADD_P(r)   1  #define RELOC_MEMORY_ADD_P(r)   1
 #undef RELOC_ADD_EXTRA  #undef RELOC_ADD_EXTRA
   #ifdef sequent                  /* might need to be on all 32k machines */
 #define RELOC_PCREL_P(r)                ((r)->r_pcrel || (r)->r_bsr)  #define RELOC_PCREL_P(r)                ((r)->r_pcrel || (r)->r_bsr)
   #else
   #define RELOC_PCREL_P(r)                ((r)->r_pcrel)
   #endif
 #define RELOC_VALUE_RIGHTSHIFT(r)       0  #define RELOC_VALUE_RIGHTSHIFT(r)       0
 #define RELOC_TARGET_SIZE(r)            ((r)->r_length)  #define RELOC_TARGET_SIZE(r)            ((r)->r_length)
 #define RELOC_TARGET_BITPOS(r)  0  #define RELOC_TARGET_BITPOS(r)  0
Line 344  static int reloc_target_bitsize[] = { Line 446  static int reloc_target_bitsize[] = {
    So, for example, the following two lines placed in an assembler     So, for example, the following two lines placed in an assembler
    input file would result in an object file which would direct gnu ld     input file would result in an object file which would direct gnu ld
    to resolve all references to symbol "foo" as references to symbol     to resolve all references to symbol "foo" as references to symbol
    "bar".      "bar".
   
         .stabs "_foo",11,0,0,0          .stabs "_foo",11,0,0,0
         .stabs "_bar",1,0,0,0          .stabs "_bar",1,0,0,0
Line 440  static int reloc_target_bitsize[] = { Line 542  static int reloc_target_bitsize[] = {
   
 /* If a this type of symbol is encountered, its name is a warning  /* If a this type of symbol is encountered, its name is a warning
    message to print each time the symbol referenced by the next symbol     message to print each time the symbol referenced by the next symbol
    table entry is referenced.        table entry is referenced.
   
    This feature may be used to allow backwards compatibility with     This feature may be used to allow backwards compatibility with
    certain functions (eg. gets) but to discourage programmers from     certain functions (eg. gets) but to discourage programmers from
Line 502  typedef Line 604  typedef
       /* Nonzero means definitions of this symbol as common have been seen,        /* Nonzero means definitions of this symbol as common have been seen,
          and the value here is the largest size specified by any of them.  */           and the value here is the largest size specified by any of them.  */
       int max_common_size;        int max_common_size;
       /* For relocatable_output, records the index of this global sym in the        /* For OUTPUT_RELOCATABLE, records the index of this global sym in the
          symbol table to be written, with the first global sym given index 0.*/           symbol table to be written, with the first global sym given index 0.*/
       int def_count;        int def_count;
       /* Nonzero means a definition of this global symbol is known to exist.        /* Nonzero means a definition of this global symbol is known to exist.
Line 525  typedef Line 627  typedef
          that it has multiple definitions, and some of them are set           that it has multiple definitions, and some of them are set
          elements, one of which has been printed out already.  */           elements, one of which has been printed out already.  */
       unsigned char multiply_defined;        unsigned char multiply_defined;
         /* Pointer to the file_entry for the last library that contained a
            subfile referencing this symbol.  */
         struct file_entry *last_library_ref;
       /* Nonzero means print a message at all refs or defs of this symbol */        /* Nonzero means print a message at all refs or defs of this symbol */
       char trace;        char trace;
     }      }
   symbol;    symbol;
   
   /* Demangler for C++.  */
   extern char *cplus_demangle ();
   
   /* Demangler function to use.  We unconditionally enable the C++ demangler
      because we assume any name it successfully demangles was probably produced
      by the C++ compiler.  Enabling it only if -lg++ was specified seems too
      much of a kludge.  */
   char *(*demangler)() = cplus_demangle;
   
 /* Number of buckets in symbol hash table */  /* Number of buckets in symbol hash table */
 #define TABSIZE 1009  #define TABSIZE 1009
   
Line 611  int nsyms; Line 725  int nsyms;
    -e sets this.  */     -e sets this.  */
 symbol *entry_symbol;  symbol *entry_symbol;
   
   /* These can be NULL if we don't actually have such a symbol.  */
 symbol *edata_symbol;   /* the symbol _edata */  symbol *edata_symbol;   /* the symbol _edata */
 symbol *etext_symbol;   /* the symbol _etext */  symbol *etext_symbol;   /* the symbol _etext */
 symbol *end_symbol;     /* the symbol _end */  symbol *end_symbol;     /* the symbol _end */
   /* We also need __{edata,etext,end} so that they can safely
      be used from an ANSI library.  */
   symbol *edata_symbol_alt;
   symbol *etext_symbol_alt;
   symbol *end_symbol_alt;
   
   /* Kinds of files potentially understood by the linker. */
   
   enum file_type { IS_UNKNOWN, IS_ARCHIVE, IS_A_OUT, IS_MACH_O };
   
 /* Each input file, and each library member ("subfile") being loaded,  /* Each input file, and each library member ("subfile") being loaded,
    has a `file_entry' structure for it.     has a `file_entry' structure for it.
   
Line 630  symbol *end_symbol; /* the symbol _end * Line 754  symbol *end_symbol; /* the symbol _end *
 struct file_entry {  struct file_entry {
   /* Name of this file.  */    /* Name of this file.  */
   char *filename;    char *filename;
   
     /* What kind of file this is. */
     enum file_type file_type;
   
   /* Name to use for the symbol giving address of text start */    /* Name to use for the symbol giving address of text start */
   /* Usually the same as filename, but for a file spec'd with -l    /* Usually the same as filename, but for a file spec'd with -l
      this is the -l switch itself rather than the filename.  */       this is the -l switch itself rather than the filename.  */
   char *local_sym_name;    char *local_sym_name;
   
   /* Describe the layout of the contents of the file */    /* Describe the layout of the contents of the file.  */
   
   /* The file's a.out header.  */    /* The text section. */
   struct exec header;    unsigned long int orig_text_address;
   /* Offset in file of GDB symbol segment, or 0 if there is none.  */    unsigned long int text_size;
   int symseg_offset;    long int text_offset;
   
     /* Text relocation. */
     unsigned long int text_reloc_size;
     long int text_reloc_offset;
   
     /* The data section. */
     unsigned long int orig_data_address;
     unsigned long int data_size;
     long int data_offset;
   
     /* Data relocation. */
     unsigned long int data_reloc_size;
     long int data_reloc_offset;
   
     /* The bss section. */
     unsigned long int orig_bss_address;
     unsigned long int bss_size;
   
     /* The symbol and string tables. */
     unsigned long int syms_size;
     long int syms_offset;
     unsigned long int strs_size;
     long int strs_offset;
   
     /* The GDB symbol segment, if any. */
     unsigned long int symseg_size;
     long int symseg_offset;
   
   #ifdef MACH_O
     /* Section ordinals from the Mach-O load commands.  These
        are compared with the n_sect fields of symbols.  */
     int text_ordinal;
     int data_ordinal;
     int bss_ordinal;
   #endif
   
   /* Describe data from the file loaded into core */    /* Describe data from the file loaded into core */
   
   /* Symbol table of the file.  */    /* Symbol table of the file.  */
   struct nlist *symbols;    struct nlist *symbols;
   /* Size in bytes of string table.  */  
   int string_size;  
   /* Pointer to the string table.    /* Pointer to the string table.
      The string table is not kept in core all the time,       The string table is not kept in core all the time,
      but when it is in core, its address is here.  */       but when it is in core, its address is here.  */
   char *strings;    char *strings;
   
   /* Next two used only if `relocatable_output' or if needed for */    /* Next two used only if OUTPUT_RELOCATABLE or if needed for */
   /* output of undefined reference line numbers. */    /* output of undefined reference line numbers. */
   
   /* Text reloc info saved by `write_text' for `coptxtrel'.  */    /* Text reloc info saved by `write_text' for `coptxtrel'.  */
Line 724  int input_desc; Line 886  int input_desc;
   
 char *output_filename;  char *output_filename;
   
 /* Descriptor for writing that file with `mywrite'.  */  /* What kind of output file to write.  */
   
 int outdesc;  enum file_type output_file_type;
   
 /* Header for that file (filled in by `write_header').  */  #ifndef DEFAULT_OUTPUT_FILE_TYPE
   #ifdef MACH_O
   #define DEFAULT_OUTPUT_FILE_TYPE IS_MACH_O
   #else
   #define DEFAULT_OUTPUT_FILE_TYPE IS_A_OUT
   #endif
   #endif
   
 struct exec outheader;  /* What `style' of output file to write.  For BSD a.out files
      this specifies OMAGIC, NMAGIC, or ZMAGIC.  For Mach-O files
      this switches between MH_OBJECT and two flavors of MH_EXECUTE.  */
   
 #ifdef COFF_ENCAPSULATE  enum output_style
 struct coffheader coffheader;    {
 int need_coff_header;      OUTPUT_UNSPECIFIED,
       OUTPUT_RELOCATABLE,         /* -r */
       OUTPUT_WRITABLE_TEXT,       /* -N */
       OUTPUT_READONLY_TEXT,       /* -n */
       OUTPUT_DEMAND_PAGED         /* -Z (default) */
     };
   
   enum output_style output_style;
   
   #ifndef DEFAULT_OUTPUT_STYLE
   #define DEFAULT_OUTPUT_STYLE OUTPUT_DEMAND_PAGED
 #endif  #endif
   
   /* Descriptor for writing that file with `mywrite'.  */
   
   int outdesc;
   
 /* The following are computed by `digest_symbols'.  */  /* The following are computed by `digest_symbols'.  */
   
 int text_size;          /* total size of text of all input files.  */  int text_size;                  /* total size of text of all input files.  */
 int data_size;          /* total size of data of all input files.  */  int text_header_size;           /* size of the file header if included in the
 int bss_size;           /* total size of bss of all input files.  */                                     text size.  */
 int text_reloc_size;    /* total size of text relocation of all input files.  */  int data_size;                  /* total size of data of all input files.  */
 int data_reloc_size;    /* total size of data relocation of all input */  int bss_size;                   /* total size of bss of all input files.  */
                         /* files.  */  int text_reloc_size;            /* total size of text relocation of all input files.  */
   int data_reloc_size;            /* total size of data relocation of all input
                                      files.  */
     
   /* The following are computed by write_header().  */
   long int output_text_offset;    /* file offset of the text section.  */
   long int output_data_offset;    /* file offset of the data section.  */
   long int output_trel_offset;    /* file offset of the text relocation info.  */
   long int output_drel_offset;    /* file offset of the data relocation info.  */
   long int output_syms_offset;    /* file offset of the symbol table.  */
   long int output_strs_offset;    /* file offset of the string table.  */
   
   /* The following are incrementally computed by write_syms(); we keep
      them here so we can examine their values afterwards.  */
   unsigned int output_syms_size;  /* total bytes of symbol table output. */
   unsigned int output_strs_size;  /* total bytes of string table output. */
   
   /* This can only be computed after the size of the string table is known.  */
   long int output_symseg_offset;  /* file offset of the symbol segment (if any).  */
   
   /* Incrementally computed by write_file_symseg().  */
   unsigned int output_symseg_size;
   
 /* Specifications of start and length of the area reserved at the end  /* Specifications of start and length of the area reserved at the end
    of the text segment for the set vectors.  Computed in 'digest_symbols' */     of the text segment for the set vectors.  Computed in 'digest_symbols' */
Line 755  int set_sect_size; Line 960  int set_sect_size;
    written. */     written. */
 unsigned long *set_vectors;  unsigned long *set_vectors;
   
 /* Amount of cleared space to leave between the text and data segments.  */  /* Amount of cleared space to leave at the end of the text segment.  */
   
 int text_pad;  int text_pad;
   
 /* Amount of bss segment to include as part of the data segment.  */  /* Amount of padding at end of data segment.  This has two parts:
      That which is before the bss segment, and that which overlaps
      with the bss segment.  */
 int data_pad;  int data_pad;
   
 /* Format of __.SYMDEF:  /* Format of __.SYMDEF:
Line 781  struct symdef { Line 987  struct symdef {
    write any padding in the output file for it.  */     write any padding in the output file for it.  */
 int text_start;  int text_start;
   
 /* Offset of default entry-pc within the text section.  */  
 int entry_offset;  
   
 /* Address we decide the data section will be loaded at.  */  /* Address we decide the data section will be loaded at.  */
 int data_start;  int data_start;
   
 /* `text-start' address is normally this much plus a page boundary.  
    This is not a user option; it is fixed for each system.  */  
 int text_start_alignment;  
   
 /* Nonzero if -T was specified in the command line.  /* Nonzero if -T was specified in the command line.
    This prevents text_start from being set later to default values.  */     This prevents text_start from being set later to default values.  */
 int T_flag_specified;  int T_flag_specified;
Line 804  int Tdata_flag_specified; Line 1003  int Tdata_flag_specified;
    and reduce the size of the bss section to match.  */     and reduce the size of the bss section to match.  */
 int specified_data_size;  int specified_data_size;
   
 /* Magic number to use for the output file, set by switch.  */  
 int magic;  
   
 /* Nonzero means print names of input files as processed.  */  /* Nonzero means print names of input files as processed.  */
 int trace_files;  int trace_files;
   
Line 822  enum { DISCARD_NONE, DISCARD_ALL, DISCAR Line 1018  enum { DISCARD_NONE, DISCARD_ALL, DISCAR
 /* 1 => write load map.  */  /* 1 => write load map.  */
 int write_map;  int write_map;
   
 /* 1 => write relocation into output file so can re-input it later.  */  /* 1 => assign space to common symbols even if OUTPUT_RELOCATABLE. */
 int relocatable_output;  
   
 /* 1 => assign space to common symbols even if `relocatable_output'.  */  
 int force_common_definition;  int force_common_definition;
   
 /* Standard directories to search for files specified by -l.  */  /* Standard directories to search for files specified by -l.  */
Line 840  char *standard_search_dirs[] = Line 1033  char *standard_search_dirs[] =
 #endif  #endif
 #endif  #endif
   
   /* If set STANDARD_SEARCH_DIRS is not searched.  */
   int no_standard_dirs;
   
 /* Actual vector of directories to search;  /* Actual vector of directories to search;
    this contains those specified with -L plus the standard ones.  */     this contains those specified with -L plus the standard ones.  */
 char **search_dirs;  char **search_dirs;
Line 847  char **search_dirs; Line 1043  char **search_dirs;
 /* Length of the vector `search_dirs'.  */  /* Length of the vector `search_dirs'.  */
 int n_search_dirs;  int n_search_dirs;
   
 /* Non zero means to create the output executable. */  /* Non zero means to create the output executable.
 /* Cleared by nonfatal errors.  */     Cleared by nonfatal errors.  */
 int make_executable;  int make_executable;
   
 /* Force the executable to be output, even if there are non-fatal  /* Force the executable to be output, even if there are non-fatal
Line 861  int force_executable; Line 1057  int force_executable;
 struct glosym **cmdline_references;  struct glosym **cmdline_references;
 int cl_refs_allocated;  int cl_refs_allocated;
   
   #ifndef bcopy
 void bcopy (), bzero ();  void bcopy (), bzero ();
 int malloc (), realloc ();  
 #ifndef alloca  
 int alloca ();  
 #endif  #endif
 int free ();  char *malloc (), *realloc ();
   void free ();
   
 int xmalloc ();  char *xmalloc ();
 int xrealloc ();  char *xrealloc ();
   void usage ();
 void fatal ();  void fatal ();
 void fatal_with_file ();  void fatal_with_file ();
 void perror_name ();  void perror_name ();
 void perror_file ();  void perror_file ();
 void error ();  void error ();
   
   int parse ();
   void initialize_text_start ();
   void initialize_data_start ();
 void digest_symbols ();  void digest_symbols ();
 void print_symbols ();  void print_symbols ();
 void load_symbols ();  void load_symbols ();
Line 905  main (argc, argv) Line 1104  main (argc, argv)
   page_size = getpagesize ();    page_size = getpagesize ();
   progname = argv[0];    progname = argv[0];
   
   #ifdef RLIMIT_STACK
     /* Avoid dumping core on large .o files.  */
     {
       struct rlimit rl;
   
       getrlimit (RLIMIT_STACK, &rl);
       rl.rlim_cur = rl.rlim_max;
       setrlimit (RLIMIT_STACK, &rl);
     }
   #endif
   
   /* Clear the cumulative info on the output file.  */    /* Clear the cumulative info on the output file.  */
   
   text_size = 0;    text_size = 0;
Line 924  main (argc, argv) Line 1134  main (argc, argv)
   discard_locals = DISCARD_NONE;    discard_locals = DISCARD_NONE;
   entry_symbol = 0;    entry_symbol = 0;
   write_map = 0;    write_map = 0;
   relocatable_output = 0;  
   force_common_definition = 0;    force_common_definition = 0;
   T_flag_specified = 0;    T_flag_specified = 0;
   Tdata_flag_specified = 0;    Tdata_flag_specified = 0;
   magic = DEFAULT_MAGIC;  
   make_executable = 1;    make_executable = 1;
   force_executable = 0;    force_executable = 0;
   set_element_prefixes = 0;    set_element_prefixes = 0;
Line 947  main (argc, argv) Line 1155  main (argc, argv)
   common_defined_global_count = 0;    common_defined_global_count = 0;
   
   /* Keep a list of symbols referenced from the command line */    /* Keep a list of symbols referenced from the command line */
   
   cl_refs_allocated = 10;    cl_refs_allocated = 10;
   cmdline_references    cmdline_references
     = (struct glosym **) xmalloc (cl_refs_allocated      = (struct glosym **) xmalloc (cl_refs_allocated
Line 957  main (argc, argv) Line 1166  main (argc, argv)
   
   decode_command (argc, argv);    decode_command (argc, argv);
   
   /* Create the symbols `etext', `edata' and `end'.  */  
   
   if (!relocatable_output)  
     symtab_init ();  
   
   /* Determine whether to count the header as part of  
      the text size, and initialize the text size accordingly.  
      This depends on the kind of system and on the output format selected.  */  
   
   N_SET_MAGIC (outheader, magic);  
 #ifdef INITIALIZE_HEADER  
   INITIALIZE_HEADER;  
 #endif  
   
   text_size = sizeof (struct exec);  
 #ifdef COFF_ENCAPSULATE  
   if (relocatable_output == 0)  
     {  
       need_coff_header = 1;  
       /* set this flag now, since it will change the values of N_TXTOFF, etc */  
       N_SET_FLAGS (outheader, N_FLAGS_COFF_ENCAPSULATE);  
       text_size += sizeof (struct coffheader);  
     }  
 #endif  
   
   text_size -= N_TXTOFF (outheader);  
   
   if (text_size < 0)  
     text_size = 0;  
   entry_offset = text_size;  
   
   if (!T_flag_specified && !relocatable_output)  
     text_start = N_TXTADDR (outheader);  
   
   /* The text-start address is normally this far past a page boundary.  */  
   text_start_alignment = text_start % page_size;  
   
   /* Load symbols of all input files.    /* Load symbols of all input files.
      Also search all libraries and decide which library members to load.  */       Also search all libraries and decide which library members to load.  */
   
   load_symbols ();    load_symbols ();
   
     /* Create various built-in symbols.  This must occur after
        all input files are loaded so that a user program can have a
        symbol named etext (for example).  */
   
     if (output_style != OUTPUT_RELOCATABLE)
       symtab_init ();
   
   /* Compute where each file's sections go, and relocate symbols.  */    /* Compute where each file's sections go, and relocate symbols.  */
   
   digest_symbols ();    digest_symbols ();
Line 1020  main (argc, argv) Line 1199  main (argc, argv)
   exit (!make_executable);    exit (!make_executable);
 }  }
   
 void decode_option ();  void add_cmdline_ref ();
   
 /* Analyze a command line argument.  
    Return 0 if the argument is a filename.  
    Return 1 if the argument is a option complete in itself.  
    Return 2 if the argument is a option which uses an argument.  
   
    Thus, the value is the number of consecutive arguments  
    that are part of options.  */  
   
 int  static struct option longopts[] =
 classify_arg (arg)  
      register char *arg;  
 {  {
   if (*arg != '-') return 0;    {"d", 0, 0, 'd'},
   switch (arg[1])    {"dc", 0, 0, 'd'},            /* For Sun compatibility. */
     {    {"dp", 0, 0, 'd'},            /* For Sun compatibility. */
     case 'A':    {"e", 1, 0, 'e'},
     case 'D':    {"n", 0, 0, 'n'},
     case 'e':    {"noinhibit-exec", 0, 0, 130},
     case 'L':    {"nostdlib", 0, 0, 133},
     case 'l':    {"o", 1, 0, 'o'},
     case 'o':    {"r", 0, 0, 'r'},
     case 'u':    {"s", 0, 0, 's'},
     case 'V':    {"t", 0, 0, 't'},
     case 'y':    {"u", 1, 0, 'u'},
       if (arg[2])    {"x", 0, 0, 'x'},
         return 1;    {"z", 0, 0, 'z'},
       return 2;    {"A", 1, 0, 'A'},
     {"Bstatic", 0, 0, 129},       /* For Sun compatibility. */
     case 'B':    {"D", 1, 0, 'D'},
       if (! strcmp (&arg[2], "static"))    {"M", 0, 0, 'M'},
         return 1;    {"N", 0, 0, 'N'},
     {"S", 0, 0, 'S'},
     case 'T':    {"T", 1, 0, 'T'},
       if (arg[2] == 0)    {"Ttext", 1, 0, 'T'},
         return 2;    {"Tdata", 1, 0, 132},
       if (! strcmp (&arg[2], "text"))    {"V", 1, 0, 'V'},
         return 2;    {"X", 0, 0, 'X'},
       if (! strcmp (&arg[2], "data"))    {0, 0, 0, 0}
         return 2;  };
       return 1;  
     }  
   
   return 1;  /* Since the Unix ld accepts -lfoo, -Lfoo, and -yfoo, we must also.
 }     This effectively prevents any long options from starting with
      one of these letters. */
   #define SHORTOPTS "-l:y:L:"
   
 /* Process the command arguments,  /* Process the command arguments,
    setting up file_table with an entry for each input file,     setting up file_table with an entry for each input file,
Line 1076  decode_command (argc, argv) Line 1245  decode_command (argc, argv)
      char **argv;       char **argv;
      int argc;       int argc;
 {  {
   register int i;    int optc, longind;
   register struct file_entry *p;    register struct file_entry *p;
   
   number_of_files = 0;    number_of_files = 0;
Line 1085  decode_command (argc, argv) Line 1254  decode_command (argc, argv)
   n_search_dirs = 0;    n_search_dirs = 0;
   search_dirs = (char **) xmalloc (sizeof (char *));    search_dirs = (char **) xmalloc (sizeof (char *));
   
   /* First compute number_of_files so we know how long to make file_table.  */    /* First compute number_of_files so we know how long to make file_table.
   /* Also process most options completely.  */       Also process most options completely.  */
   
   for (i = 1; i < argc; i++)    while ((optc = getopt_long_only (argc, argv, SHORTOPTS, longopts, &longind))
            != EOF)
     {      {
       register int code = classify_arg (argv[i]);        if (optc == 0)
       if (code)          optc = longopts[longind].val;
   
         switch (optc)
         {          {
           if (i + code > argc)          case '?':
             fatal ("no argument following %s\n", argv[i]);            usage (0, 0);
             break;
   
           case 1:
             /* Non-option argument. */
             number_of_files++;
             break;
   
           case 'd':
             force_common_definition = 1;
             break;
   
           case 'e':
             entry_symbol = getsym (optarg);
             if (!entry_symbol->defined && !entry_symbol->referenced)
               undefined_global_sym_count++;
             entry_symbol->referenced = 1;
             add_cmdline_ref (entry_symbol);
             break;
   
           case 'l':
             number_of_files++;
             break;
   
           case 'n':
             if (output_style && output_style != OUTPUT_READONLY_TEXT)
               fatal ("illegal combination of -n with -N, -r, or -z", (char *) 0);
             output_style = OUTPUT_READONLY_TEXT;
             break;
   
           case 130:               /* -noinhibit-exec */
             force_executable = 1;
             break;
   
           case 133:               /* -nostdlib */
             no_standard_dirs = 1;
             break;
   
           case 'o':
             output_filename = optarg;
             break;
   
           case 'r':
             if (output_style && output_style != OUTPUT_RELOCATABLE)
               fatal ("illegal combination of -r with -N, -n, or -z", (char *) 0);
             output_style = OUTPUT_RELOCATABLE;
             text_start = 0;
             break;
   
           case 's':
             strip_symbols = STRIP_ALL;
             break;
   
           case 't':
             trace_files = 1;
             break;
   
           case 'u':
             {
               register symbol *sp = getsym (optarg);
   
               if (!sp->defined && !sp->referenced)
                 undefined_global_sym_count++;
               sp->referenced = 1;
               add_cmdline_ref (sp);
             }
             break;
   
           case 'x':
             discard_locals = DISCARD_ALL;
             break;
             
           case 'y':
             {
               register symbol *sp = getsym (optarg);
   
               sp->trace = 1;
             }
             break;
   
           case 'z':
             if (output_style && output_style != OUTPUT_DEMAND_PAGED)
               fatal ("illegal combination of -z with -N, -n, or -r", (char *) 0);
             output_style = OUTPUT_DEMAND_PAGED;
             break;
   
           case 'A':
             number_of_files++;
             break;
   
           case 129:               /* -Bstatic. */
             /* Ignore. */
             break;
   
           case 'D':
             specified_data_size = parse (optarg, "%x", "invalid argument to -D");
             break;
   
           case 'L':
             n_search_dirs++;
             search_dirs = (char **)
               xrealloc (search_dirs, n_search_dirs * sizeof (char *));
             search_dirs[n_search_dirs - 1] = optarg;
             break;
             
           case 'M':
             write_map = 1;
             break;
   
           case 'N':
             if (output_style && output_style != OUTPUT_WRITABLE_TEXT)
               fatal ("illegal combination of -N with -n, -r, or -z", (char *) 0);
             output_style = OUTPUT_WRITABLE_TEXT;
             break;
   
           case 'S':
             strip_symbols = STRIP_DEBUGGER;
             break;
   
           case 'T':
             text_start = parse (optarg, "%x", "invalid argument to -Ttext");
             T_flag_specified = 1;
             break;
   
           decode_option (argv[i], argv[i+1]);          case 132:               /* -Tdata addr */
             data_start = parse (optarg, "%x", "invalid argument to -Tdata");
             Tdata_flag_specified = 1;
             break;
   
           if (argv[i][1] == 'l' || argv[i][1] == 'A')          case 'V':
             number_of_files++;            {
               struct string_list_element *new
                 = (struct string_list_element *)
                   xmalloc (sizeof (struct string_list_element));
               
               new->str = optarg;
               new->next = set_element_prefixes;
               set_element_prefixes = new;
             }
             break;
   
           i += code - 1;          case 'X':
             discard_locals = DISCARD_L;
             break;
         }          }
       else  
         number_of_files++;  
     }      }
   
   if (!number_of_files)    if (!number_of_files)
     fatal ("no input files", 0);      usage ("no input files", 0);
   
   p = file_table    p = file_table
     = (struct file_entry *) xmalloc (number_of_files * sizeof (struct file_entry));      = (struct file_entry *) xmalloc (number_of_files * sizeof (struct file_entry));
   bzero (p, number_of_files * sizeof (struct file_entry));    bzero (p, number_of_files * sizeof (struct file_entry));
   
   /* Now scan again and fill in file_table.  */    /* Now scan again and fill in file_table.
   /* All options except -A and -l are ignored here.  */       All options except -A and -l are ignored here.  */
   
   for (i = 1; i < argc; i++)    optind = 0;                   /* Reset getopt. */
     while ((optc = getopt_long_only (argc, argv, SHORTOPTS, longopts, &longind))
            != EOF)
     {      {
       register int code = classify_arg (argv[i]);        if (optc == 0)
           optc = longopts[longind].val;
   
       if (code)        switch (optc)
         {          {
           char *string;          case 1:
           if (code == 2)            /* Non-option argument. */
             string = argv[i+1];            p->filename = optarg;
           else            p->local_sym_name = optarg;
             string = &argv[i][2];            p++;
             break;
   
           if (argv[i][1] == 'A')          case 'A':
             {            if (p != file_table)
               if (p != file_table)              usage ("-A specified before an input file other than the first");
                 fatal ("-A specified before an input file other than the first");            p->filename = optarg;
             p->local_sym_name = optarg;
             p->just_syms_flag = 1;
             p++;
             break;
   
               p->filename = string;          case 'l':
               p->local_sym_name = string;            p->filename = concat ("lib", optarg, ".a");
               p->just_syms_flag = 1;            p->local_sym_name = concat ("-l", optarg, "");
               p++;            p->search_dirs_flag = 1;
             }  
           if (argv[i][1] == 'l')  
             {  
               p->filename = concat ("lib", string, ".a");  
               p->local_sym_name = concat ("-l", string, "");  
               p->search_dirs_flag = 1;  
               p++;  
             }  
           i += code - 1;  
         }  
       else  
         {  
           p->filename = argv[i];  
           p->local_sym_name = argv[i];  
           p++;            p++;
             break;
         }          }
     }      }
   
     if (!output_file_type)
       output_file_type = DEFAULT_OUTPUT_FILE_TYPE;
   
     if (!output_style)
       output_style = DEFAULT_OUTPUT_STYLE;
   
   #if 0
     /* THIS CONSISTENCY CHECK BELONGS SOMEWHERE ELSE.  */
   /* Now check some option settings for consistency.  */    /* Now check some option settings for consistency.  */
   
 #ifdef NMAGIC    if ((output_style == OUTPUT_READONLY_TEXT || output_style == OUTPUT_DEMAND_PAGED)
   if ((magic == ZMAGIC || magic == NMAGIC)  
 #else  
   if ((magic == ZMAGIC)  
 #endif  
       && (text_start - text_start_alignment) & (page_size - 1))        && (text_start - text_start_alignment) & (page_size - 1))
     fatal ("-T argument not multiple of page size, with sharable output", 0);      usage ("-T argument not multiple of page size, with sharable output", 0);
   #endif
   
   /* Append the standard search directories to the user-specified ones.  */    /* Append the standard search directories to the user-specified ones.  */
   {    if (!no_standard_dirs)
     int n = sizeof standard_search_dirs / sizeof standard_search_dirs[0];      {
     n_search_dirs += n;        int n = sizeof standard_search_dirs / sizeof standard_search_dirs[0];
     search_dirs        n_search_dirs += n;
       = (char **) xrealloc (search_dirs, n_search_dirs * sizeof (char *));        search_dirs
     bcopy (standard_search_dirs, &search_dirs[n_search_dirs - n],          = (char **) xrealloc (search_dirs, n_search_dirs * sizeof (char *));
            n * sizeof (char *));        bcopy (standard_search_dirs, &search_dirs[n_search_dirs - n],
   }               n * sizeof (char *));
       }
 }  }
   
   
Line 1192  add_cmdline_ref (sp) Line 1499  add_cmdline_ref (sp)
   if (ptr >= cmdline_references + cl_refs_allocated - 1)    if (ptr >= cmdline_references + cl_refs_allocated - 1)
     {      {
       int diff = ptr - cmdline_references;        int diff = ptr - cmdline_references;
         
       cl_refs_allocated *= 2;        cl_refs_allocated *= 2;
       cmdline_references = (struct glosym **)        cmdline_references = (struct glosym **)
         xrealloc (cmdline_references,          xrealloc (cmdline_references,
                  cl_refs_allocated * sizeof (struct glosym *));                   cl_refs_allocated * sizeof (struct glosym *));
       ptr = cmdline_references + diff;        ptr = cmdline_references + diff;
     }      }
     
   *ptr++ = sp;    *ptr++ = sp;
   *ptr = (struct glosym *) 0;    *ptr = (struct glosym *) 0;
 }  }
       
 int  int
 set_element_prefixed_p (name)  set_element_prefixed_p (name)
      char *name;       char *name;
Line 1221  set_element_prefixed_p (name) Line 1528  set_element_prefixed_p (name)
     }      }
   return 0;    return 0;
 }  }
   
   /* Convenient functions for operating on one or all files being
      loaded.  */
   void print_file_name ();
   
 int parse ();  /* Call FUNCTION on each input file entry.
      Do not call for entries for libraries;
 /* Record an option and arrange to act on it later.     instead, call once for each library member that is being loaded.
    ARG should be the following command argument,  
    which may or may not be used by this option.  
   
    The `l' and `A' options are ignored here since they actually     FUNCTION receives two arguments: the entry, and ARG.  */
    specify input files.  */  
   
 void  void
 decode_option (swt, arg)  each_file (function, arg)
      register char *swt, *arg;       register void (*function)();
        register int arg;
 {  {
   /* We get Bstatic from gcc on suns.  */    register int i;
   if (! strcmp (swt + 1, "Bstatic"))  
     return;  
   if (! strcmp (swt + 1, "Ttext"))  
     {  
       text_start = parse (arg, "%x", "invalid argument to -Ttext");  
       T_flag_specified = 1;  
       return;  
     }  
   if (! strcmp (swt + 1, "Tdata"))  
     {  
       data_start = parse (arg, "%x", "invalid argument to -Tdata");  
       Tdata_flag_specified = 1;  
       return;  
     }  
   if (! strcmp (swt + 1, "noinhibit-exec"))  
     {  
       force_executable = 1;  
       return;  
     }  
   
   if (swt[2] != 0)  
     arg = &swt[2];  
   
   switch (swt[1])    for (i = 0; i < number_of_files; i++)
     {      {
     case 'A':        register struct file_entry *entry = &file_table[i];
       return;        if (entry->library_flag)
           {
             register struct file_entry *subentry = entry->subfiles;
             for (; subentry; subentry = subentry->chain)
               (*function) (subentry, arg);
           }
         else
           (*function) (entry, arg);
       }
   }
   
     case 'D':  /* Call FUNCTION on each input file entry until it returns a non-zero
       specified_data_size = parse (arg, "%x", "invalid argument to -D");     value.  Return this value.
       return;     Do not call for entries for libraries;
      instead, call once for each library member that is being loaded.
   
     case 'd':     FUNCTION receives two arguments: the entry, and ARG.  It must be a
       force_common_definition = 1;     function returning unsigned long (though this can probably be fudged). */
       return;  
   
     case 'e':  
       entry_symbol = getsym (arg);  
       if (!entry_symbol->defined && !entry_symbol->referenced)  
         undefined_global_sym_count++;  
       entry_symbol->referenced = 1;  
       add_cmdline_ref (entry_symbol);  
       return;  
   
     case 'l':  
       return;  
   
     case 'L':  
       n_search_dirs++;  
       search_dirs  
         = (char **) xrealloc (search_dirs, n_search_dirs * sizeof (char *));  
       search_dirs[n_search_dirs - 1] = arg;  
       return;  
   
     case 'M':  
       write_map = 1;  
       return;  
   
     case 'N':  
       magic = OMAGIC;  
       return;  
   
 #ifdef NMAGIC  
     case 'n':  
       magic = NMAGIC;  
       return;  
 #endif  
   
     case 'o':  
       output_filename = arg;  
       return;  
   
     case 'r':  
       relocatable_output = 1;  
       magic = OMAGIC;  
       text_start = 0;  
       return;  
   
     case 'S':  
       strip_symbols = STRIP_DEBUGGER;  
       return;  
   
     case 's':  
       strip_symbols = STRIP_ALL;  
       return;  
   
     case 'T':  
       text_start = parse (arg, "%x", "invalid argument to -T");  
       T_flag_specified = 1;  
       return;  
   
     case 't':  
       trace_files = 1;  
       return;  
   
     case 'u':  
       {  
         register symbol *sp = getsym (arg);  
         if (!sp->defined && !sp->referenced)  
           undefined_global_sym_count++;  
         sp->referenced = 1;  
         add_cmdline_ref (sp);  
       }  
       return;  
   
     case 'V':  
       {  
         struct string_list_element *new  
           = (struct string_list_element *)  
             xmalloc (sizeof (struct string_list_element));  
   
         new->str = arg;  
         new->next = set_element_prefixes;  
         set_element_prefixes = new;  
         return;  
       }  
   
     case 'X':  
       discard_locals = DISCARD_L;  
       return;  
   
     case 'x':  
       discard_locals = DISCARD_ALL;  
       return;  
   
     case 'y':  
       {  
         register symbol *sp = getsym (&swt[2]);  
         sp->trace = 1;  
       }  
       return;  
   
     case 'z':  
       magic = ZMAGIC;  
       return;  
   
     default:  
       fatal ("invalid command option `%s'", swt);  
     }  
 }  
   
 /** Convenient functions for operating on one or all files being */  
  /** loaded.  */  
 void print_file_name ();  
   
 /* Call FUNCTION on each input file entry.  
    Do not call for entries for libraries;  
    instead, call once for each library member that is being loaded.  
   
    FUNCTION receives two arguments: the entry, and ARG.  */  
   
 void  
 each_file (function, arg)  
      register void (*function)();  
      register int arg;  
 {  
   register int i;  
   
   for (i = 0; i < number_of_files; i++)  
     {  
       register struct file_entry *entry = &file_table[i];  
       if (entry->library_flag)  
         {  
           register struct file_entry *subentry = entry->subfiles;  
           for (; subentry; subentry = subentry->chain)  
             (*function) (subentry, arg);  
         }  
       else  
         (*function) (entry, arg);  
     }  
 }  
   
 /* Call FUNCTION on each input file entry until it returns a non-zero  
    value.  Return this value.  
    Do not call for entries for libraries;  
    instead, call once for each library member that is being loaded.  
   
    FUNCTION receives two arguments: the entry, and ARG.  It must be a  
    function returning unsigned long (though this can probably be fudged). */  
   
 unsigned long  unsigned long
 check_each_file (function, arg)  check_each_file (function, arg)
Line 1494  file_open (entry) Line 1646  file_open (entry)
   
   if (input_file) file_close ();    if (input_file) file_close ();
   
   if (entry->search_dirs_flag)    if (entry->search_dirs_flag && n_search_dirs)
     {      {
       register char **p = search_dirs;  
       int i;        int i;
   
       for (i = 0; i < n_search_dirs; i++)        for (i = 0; i < n_search_dirs; i++)
Line 1580  get_file_name (entry) Line 1731  get_file_name (entry)
   
 /* Medium-level input routines for rel files.  */  /* Medium-level input routines for rel files.  */
   
 /* Read a file's header into the proper place in the file_entry.  /* Determine whether the given ENTRY is an archive, a BSD a.out file,
      a Mach-O file, or whatever.  DESC is the descriptor on which the
      file is open.  */
   void
   deduce_file_type(desc, entry)
        int desc;
        struct file_entry *entry;
   {
     int len;
   
     {
       char magic[SARMAG];
       
       lseek (desc, entry->starting_offset, 0);
       len = read (desc, magic, SARMAG);
       if (len == SARMAG && !strncmp(magic, ARMAG, SARMAG))
         {
           entry->file_type = IS_ARCHIVE;
           return;
         }
   #ifdef LARMAG
       /* Odd hack for Tektronix. */
       if (len == SARMAG && !strncmp(magic, LARMAG, SARMAG))
         {
           entry->file_type = IS_ARCHIVE;
           return;
         }
   #endif
     }
   
   #ifdef A_OUT
     {
       struct exec hdr;
   
       lseek (desc, entry->starting_offset, 0);
   #ifdef COFF_ENCAPSULATE
       if (entry->just_syms_flag)
         /* Since a file given with -A will have a coff header, unlike normal
           input files, we need to skip over it.  */
         lseek (desc, sizeof (struct coffheader), SEEK_CUR);
   #endif
       len = read (desc, (char *) &hdr, sizeof (struct exec));
       if (len == sizeof (struct exec) && !N_BADMAG (hdr))
         {
           entry->file_type = IS_A_OUT;
           return;
         }
     }
   #endif
   
   #ifdef MACH_O
     {
       struct mach_header hdr;
   
       lseek (desc, entry->starting_offset, 0);
       len = read (desc, (char *) &hdr, sizeof (struct mach_header));
       if (len == sizeof (struct mach_header) && hdr.magic == MH_MAGIC)
         {
           entry->file_type = IS_MACH_O;
           return;
         }
     }
   #endif
   
     fatal_with_file ("malformed input file (not rel or archive) ", entry);
   }
   
   #ifdef A_OUT
   /* Read an a.out file's header and set up the fields of
      the ENTRY accordingly.  DESC is the descriptor on which
      the file is open.  */
   void
   read_a_out_header (desc, entry)
        int desc;
        struct file_entry *entry;
   {
     register int len;
     struct exec hdr;
     struct stat st;
   
     lseek (desc, entry->starting_offset, 0);
   
   #ifdef COFF_ENCAPSULATE
     if (entry->just_syms_flag)
       /* Since a file given with -A will have a coff header, unlike normal
          input files, we need to skip over it.  */
       lseek (desc, sizeof (struct coffheader), SEEK_CUR);
   #endif
   
     read (desc, (char *) &hdr, sizeof (struct exec));
   
   #ifdef READ_HEADER_HOOK
     READ_HEADER_HOOK(hdr.a_machtype);
   #endif
   
     if (entry->just_syms_flag)
       entry->orig_text_address = N_TXTADDR(hdr);
     else
       entry->orig_text_address = 0;
     entry->text_size = hdr.a_text;
     entry->text_offset = N_TXTOFF(hdr);
   
     entry->text_reloc_size = hdr.a_trsize;
   #ifdef N_TRELOFF
     entry->text_reloc_offset = N_TRELOFF(hdr);
   #else
   #ifdef N_DATOFF
     entry->text_reloc_offset = N_DATOFF(hdr) + hdr.a_data;
   #else
     entry->text_reloc_offset = N_TXTOFF(hdr) + hdr.a_text + hdr.a_data;
   #endif
   #endif
   
     if (entry->just_syms_flag)
       entry->orig_data_address = N_DATADDR(hdr);
     else
       entry->orig_data_address = entry->text_size;
     entry->data_size = hdr.a_data;
   #ifdef N_DATOFF
     entry->data_offset = N_DATOFF(hdr);
   #else
     entry->data_offset = N_TXTOFF(hdr) + hdr.a_text;
   #endif
   
   #ifdef NMAGIC
     /* If this is an NMAGIC file, then even though the text and data
        are contiguous in the input file, the data has _already_ been
        relocated to the next page boundary.
        Change orig_data_address to reflect this.  */
   #ifdef N_MAGIC
     if (N_MAGIC(hdr) == NMAGIC)
   #else
     if (hdr.a_magic == NMAGIC)
   #endif
       entry->orig_data_address += (((hdr.a_text + page_size - 1)
                                     & ~(page_size - 1)) - hdr.a_text);
   #endif
   
     entry->data_reloc_size = hdr.a_drsize;
   #ifdef N_DRELOFF
     entry->data_reloc_offset = N_DRELOFF(hdr);
   #else
     entry->data_reloc_offset = entry->text_reloc_offset + entry->text_reloc_size;
   #endif
   
   #ifdef N_BSSADDR
     if (entry->just_syms_flag)
       entry->orig_bss_address = N_BSSADDR(hdr);
     else
   #endif
     entry->orig_bss_address = entry->orig_data_address + entry->data_size;
     entry->bss_size = hdr.a_bss;
   
     entry->syms_size = hdr.a_syms;
     entry->syms_offset = N_SYMOFF(hdr);
     entry->strs_offset = N_STROFF(hdr);
     lseek(desc, entry->starting_offset + entry->strs_offset, 0);
     if (read(desc, (char *) &entry->strs_size, sizeof (unsigned long int))
         != sizeof (unsigned long int))
       fatal_with_file ("failure reading string table size of ", entry);
   
     if (!entry->superfile)
       {
         fstat(desc, &st);
         if (st.st_size > entry->strs_offset + entry->strs_size)
           {
             entry->symseg_size = st.st_size - (entry->strs_offset + entry->strs_size);
             entry->symseg_offset = entry->strs_offset + entry->strs_size;
           }
       }
     else
       if (entry->total_size > entry->strs_offset + entry->strs_size)
         {
           entry->symseg_size = entry->total_size - (entry->strs_offset + entry->strs_size);
           entry->symseg_offset = entry->strs_offset + entry->strs_size;
         }
   }
   #endif
   
   #ifdef MACH_O
   /* Read a Mach-O file's header.  DESC is the descriptor on which the
      file is open, and ENTRY is the file's entry.  */
   void
   read_mach_o_header (desc, entry)
        int desc;
        struct file_entry *entry;
   {
     struct mach_header mach_header;
     char *hdrbuf;
     struct load_command *load_command;
     struct segment_command *segment_command;
     struct section *section;
     struct symtab_command *symtab_command;
   #ifdef LC_SYMSEG
     struct symseg_command *symseg_command;
   #endif;
     int ordinal;
     int symtab_seen, symseg_seen;
     int len, cmd, seg;
   
     entry->text_ordinal = entry->data_ordinal = entry->bss_ordinal = 0;
     symtab_seen = symseg_seen = 0;
     ordinal = 1;
   
     lseek (desc, entry->starting_offset, 0);
     len = read (desc, (char *) &mach_header, sizeof (struct mach_header));
     if (len != sizeof (struct mach_header))
       fatal_with_file ("failure reading Mach-O header of ", entry);
     if (mach_header.filetype != MH_OBJECT && mach_header.filetype != MH_EXECUTE)
       fatal_with_file ("unsupported Mach-O file type (not MH_OBJECT or MH_EXECUTE) in ", entry);
     hdrbuf = xmalloc (mach_header.sizeofcmds);
     len = read (desc, hdrbuf, mach_header.sizeofcmds);
     if (len != mach_header.sizeofcmds)
       fatal_with_file ("failure reading Mach-O load commands of ", entry);
     load_command = (struct load_command *) hdrbuf;
     for (cmd = 0; cmd < mach_header.ncmds; ++cmd)
       {
         switch (load_command->cmd)
           {
           case LC_SEGMENT:
             segment_command = (struct segment_command *) load_command;
             section = (struct section *) ((char *) (segment_command + 1));
             for (seg = 0; seg < segment_command->nsects; ++seg, ++section, ++ordinal)
               {
                 if (!strncmp(SECT_TEXT, section->sectname, sizeof section->sectname))
                   if (entry->text_ordinal)
                     fatal_with_file ("more than one __text section in ", entry);
                   else
                     {
                       entry->text_ordinal = ordinal;
                       entry->orig_text_address = section->addr;
                       entry->text_size = section->size;
                       entry->text_offset = section->offset;
                       entry->text_reloc_size = section->nreloc * sizeof (struct relocation_info);
                       entry->text_reloc_offset = section->reloff;
                     }
                 else if (!strncmp(SECT_DATA, section->sectname, sizeof section->sectname))
                   if (entry->data_ordinal)
                     fatal_with_file ("more than one __data section in ", entry);
                   else
                     {
                       entry->data_ordinal = ordinal;
                       entry->orig_data_address = section->addr;
                       entry->data_size = section->size;
                       entry->data_offset = section->offset;
                       entry->data_reloc_size = section->nreloc * sizeof (struct relocation_info);
                       entry->data_reloc_offset = section->reloff;
                     }
                 else if (!strncmp(SECT_BSS, section->sectname, sizeof section->sectname))
                   if (entry->bss_ordinal)
                     fatal_with_file ("more than one __bss section in ", entry);
                   else
                     {
                       entry->bss_ordinal = ordinal;
                       entry->orig_bss_address = section->addr;
                       entry->bss_size = section->size;
                     }
                 else
                   if (section->size != 0)
                     fprintf (stderr, "%s: warning: unknown section `%.*s' in %s\n",
                              progname, sizeof section->sectname, section->sectname,
                              entry->filename);
               }
             break;
           case LC_SYMTAB:
             if (symtab_seen)
                 fatal_with_file ("more than one LC_SYMTAB in ", entry);
             else
               {
                 symtab_seen = 1;
                 symtab_command = (struct symtab_command *) load_command;
                 entry->syms_size = symtab_command->nsyms * sizeof (struct nlist);
                 entry->syms_offset = symtab_command->symoff;
                 entry->strs_size = symtab_command->strsize;
                 entry->strs_offset = symtab_command->stroff;
               }
             break;
   #ifdef LC_SYMSEG
           case LC_SYMSEG:
             if (symseg_seen)
               fatal_with_file ("more than one LC_SYMSEG in ", entry);
             else
               {
                 symseg_seen = 1;
                 symseg_command = (struct symseg_command *) load_command;
                 entry->symseg_size = symseg_command->size;
                 entry->symseg_offset = symseg_command->offset;
               }
             break;
   #endif
           }
         load_command = (struct load_command *)
           ((char *) load_command + load_command->cmdsize);
       }
   
     free (hdrbuf);
   
     if (!symtab_seen)
       fprintf (stderr, "%s: no symbol table in %s\n", progname, entry->filename);
   }
   #endif
   
   /* Read a file's header info into the proper place in the file_entry.
    DESC is the descriptor on which the file is open.     DESC is the descriptor on which the file is open.
    ENTRY is the file's entry.  */     ENTRY is the file's entry.
      Switch in the file_type to determine the appropriate actual
      header reading routine to call.  */
   
 void  void
 read_header (desc, entry)  read_header (desc, entry)
      int desc;       int desc;
      register struct file_entry *entry;       register struct file_entry *entry;
 {  {
   register int len;    if (!entry->file_type)
   struct exec *loc = (struct exec *) &entry->header;      deduce_file_type (desc, entry);
   
   lseek (desc, entry->starting_offset, 0);    switch (entry->file_type)
   len = read (desc, loc, sizeof (struct exec));      {
   if (len != sizeof (struct exec))      case IS_ARCHIVE:
     fatal_with_file ("failure reading header of ", entry);      default:
   if (N_BADMAG (*loc))        /* Should never happen. */
     fatal_with_file ("bad magic number in ", entry);        abort ();
   
   #ifdef A_OUT
       case IS_A_OUT:
         read_a_out_header (desc, entry);
         break;
   #endif
   
   #ifdef MACH_O
       case IS_MACH_O:
         read_mach_o_header (desc, entry);
         break;
   #endif
       }
   
   entry->header_read_flag = 1;    entry->header_read_flag = 1;
 }  }
   
   #ifdef MACH_O
   void translate_mach_o_symbols ();
   #endif
   
 /* Read the symbols of file ENTRY into core.  /* Read the symbols of file ENTRY into core.
    Assume it is already open, on descriptor DESC.     Assume it is already open, on descriptor DESC.  */
    Also read the length of the string table, which follows the symbol table,  
    but don't read the contents of the string table.  */  
   
 void  void
 read_entry_symbols (desc, entry)  read_entry_symbols (desc, entry)
Line 1617  read_entry_symbols (desc, entry) Line 2087  read_entry_symbols (desc, entry)
   if (!entry->header_read_flag)    if (!entry->header_read_flag)
     read_header (desc, entry);      read_header (desc, entry);
   
   entry->symbols = (struct nlist *) xmalloc (entry->header.a_syms);    entry->symbols = (struct nlist *) xmalloc (entry->syms_size);
   
   lseek (desc, N_SYMOFF (entry->header) + entry->starting_offset, 0);    lseek (desc, entry->syms_offset + entry->starting_offset, 0);
   if (entry->header.a_syms != read (desc, entry->symbols, entry->header.a_syms))    if (entry->syms_size != read (desc, entry->symbols, entry->syms_size))
     fatal_with_file ("premature end of file in symbols of ", entry);      fatal_with_file ("premature end of file in symbols of ", entry);
   
   lseek (desc, N_STROFF (entry->header) + entry->starting_offset, 0);  #ifdef MACH_O
   if (sizeof str_size != read (desc, &str_size, sizeof str_size))    if (entry->file_type == IS_MACH_O)
     fatal_with_file ("bad string table size in ", entry);      translate_mach_o_symbols (entry);
   #endif
   entry->string_size = str_size;  
 }  }
   
 /* Read the string table of file ENTRY into core.  /* Read the string table of file ENTRY into core.
    Assume it is already open, on descriptor DESC.     Assume it is already open, on descriptor DESC.  */
    Also record whether a GDB symbol segment follows the string table.  */  
   
 void  void
 read_entry_strings (desc, entry)  read_entry_strings (desc, entry)
Line 1644  read_entry_strings (desc, entry) Line 2112  read_entry_strings (desc, entry)
   if (!entry->header_read_flag)    if (!entry->header_read_flag)
     read_header (desc, entry);      read_header (desc, entry);
   
   lseek (desc, N_STROFF (entry->header) + entry->starting_offset, 0);    lseek (desc, entry->strs_offset + entry->starting_offset, 0);
   if (entry->string_size != read (desc, entry->strings, entry->string_size))    if (entry->strs_size != read (desc, entry->strings, entry->strs_size))
     fatal_with_file ("premature end of file in strings of ", entry);      fatal_with_file ("premature end of file in strings of ", entry);
   
   /* While we are here, see if the file has a symbol segment at the end.  
      For a separate file, just try reading some more.  
      For a library member, compare current pos against total size.  */  
   if (entry->superfile)  
     {  
       if (entry->total_size == N_STROFF (entry->header) + entry->string_size)  
         return;  
     }  
   else  
     {  
       buffer = read (desc, &buffer, sizeof buffer);  
       if (buffer == 0)  
         return;  
       if (buffer != sizeof buffer)  
         fatal_with_file ("premature end of file in GDB symbol segment of ", entry);  
     }  
   
   entry->symseg_offset = N_STROFF (entry->header) + entry->string_size;  
 }  }
   
 /* Read in the symbols of all input files.  */  /* Read in the symbols of all input files.  */
Line 1698  read_file_symbols (entry) Line 2147  read_file_symbols (entry)
      register struct file_entry *entry;       register struct file_entry *entry;
 {  {
   register int desc;    register int desc;
   register int len;  
   struct exec hdr;  
   
   desc = file_open (entry);    desc = file_open (entry);
   
   len = read (desc, &hdr, sizeof hdr);    if (!entry->file_type)
   if (len != sizeof hdr)      deduce_file_type (desc, entry);
     fatal_with_file ("failure reading header of ", entry);  
   
   if (!N_BADMAG (hdr))    if (entry->file_type == IS_ARCHIVE)
       {
         entry->library_flag = 1;
         search_library (desc, entry);
       }
     else
     {      {
       read_entry_symbols (desc, entry);        read_entry_symbols (desc, entry);
       entry->strings = (char *) alloca (entry->string_size);        entry->strings = (char *) alloca (entry->strs_size);
       read_entry_strings (desc, entry);        read_entry_strings (desc, entry);
       enter_file_symbols (entry);        enter_file_symbols (entry);
       entry->strings = 0;        entry->strings = 0;
     }      }
   else  
     {  
       char armag[SARMAG];  
   
       lseek (desc, 0, 0);  
       if (SARMAG != read (desc, armag, SARMAG) || strncmp (armag, ARMAG, SARMAG))  
         fatal_with_file ("malformed input file (not rel or archive) ", entry);  
       entry->library_flag = 1;  
       search_library (desc, entry);  
     }  
   
   file_close ();    file_close ();
 }  }
Line 1737  enter_file_symbols (entry) Line 2178  enter_file_symbols (entry)
 {  {
   register struct nlist    register struct nlist
     *p,      *p,
     *end = entry->symbols + entry->header.a_syms / sizeof (struct nlist);      *end = entry->symbols + entry->syms_size / sizeof (struct nlist);
   int lowest_set_vector = -1;  
   
   if (trace_files) prline_file_name (entry, stderr);    if (trace_files) prline_file_name (entry, stderr);
   
Line 1752  enter_file_symbols (entry) Line 2192  enter_file_symbols (entry)
       if (SET_ELEMENT_P (p->n_type))        if (SET_ELEMENT_P (p->n_type))
         {          {
           set_symbol_count++;            set_symbol_count++;
           if (!relocatable_output)            if (output_style != OUTPUT_RELOCATABLE)
             enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);              enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);
         }          }
       else if (p->n_type == N_WARNING)        else if (p->n_type == N_WARNING)
Line 1771  enter_file_symbols (entry) Line 2211  enter_file_symbols (entry)
           else            else
             {              {
               symbol *sp;                symbol *sp;
               char *sname = p->n_un.n_strx + entry->strings;                 char *sname = p->n_un.n_strx + entry->strings;
               /* Deal with the warning symbol.  */                /* Deal with the warning symbol.  */
               enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);                enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);
               sp = getsym (sname);                sp = getsym (sname);
Line 1824  enter_global_ref (nlist_p, name, entry) Line 2264  enter_global_ref (nlist_p, name, entry)
   sp->refs = nlist_p;    sp->refs = nlist_p;
   
   sp->referenced = 1;    sp->referenced = 1;
     sp->last_library_ref = entry->superfile;
   
   if (type != (N_UNDF | N_EXT) || nlist_p->n_value)    if (type != (N_UNDF | N_EXT) || nlist_p->n_value)
     {      {
       if (!sp->defined || sp->defined == (N_UNDF | N_EXT))        if (!sp->defined || sp->defined == (N_UNDF | N_EXT))
Line 1862  enter_global_ref (nlist_p, name, entry) Line 2304  enter_global_ref (nlist_p, name, entry)
           /* Indirect symbols value should be modified to point            /* Indirect symbols value should be modified to point
              a symbol being equivalenced to. */               a symbol being equivalenced to. */
           nlist_p->n_value            nlist_p->n_value
   #ifndef NeXT
             = (unsigned int) getsym ((nlist_p + 1)->n_un.n_strx              = (unsigned int) getsym ((nlist_p + 1)->n_un.n_strx
                                      + entry->strings);                                       + entry->strings);
           if ((symbol *) nlist_p->n_value == sp)  #else
               /* NeXT also has indirection but they do it weirdly. */
               = (unsigned int) getsym (nlist_p->n_value + entry->strings);
   #endif
             if ((symbol *) nlist_p->n_value == sp)
             {              {
               /* Somebody redefined a symbol to be itself.  */                /* Somebody redefined a symbol to be itself.  */
               fprintf (stderr, "%s: Symbol %s indirected to itself.\n",                fprintf (stderr, "%s: Symbol %s indirected to itself.\n",
Line 1909  enter_global_ref (nlist_p, name, entry) Line 2356  enter_global_ref (nlist_p, name, entry)
   if (sp->trace)    if (sp->trace)
     {      {
       register char *reftype;        register char *reftype;
       switch (type & N_TYPE)        switch (type & ~N_EXT)
         {          {
         case N_UNDF:          case N_UNDF:
           if (nlist_p->n_value)            if (nlist_p->n_value)
Line 1954  enter_global_ref (nlist_p, name, entry) Line 2401  enter_global_ref (nlist_p, name, entry)
           break;            break;
   
         case N_INDR:          case N_INDR:
           reftype = (char *) alloca (23            reftype = (char *) alloca (23 + strlen (((symbol *) nlist_p->n_value)->name));
                                      + strlen ((nlist_p + 1)->n_un.n_strx  
                                                + entry->strings));  
           sprintf (reftype, "defined equivalent to %s",            sprintf (reftype, "defined equivalent to %s",
                    (nlist_p + 1)->n_un.n_strx + entry->strings);                     ((symbol *) nlist_p->n_value)->name);
           break;            break;
   
 #ifdef sequent  #ifdef sequent
Line 1975  enter_global_ref (nlist_p, name, entry) Line 2420  enter_global_ref (nlist_p, name, entry)
           reftype = "shared BSS";            reftype = "shared BSS";
           break;            break;
 */  */
   #endif
   
         default:          default:
           reftype = "I don't know this type";            reftype = "I don't know this type";
           break;            break;
 #endif  
         }          }
   
       fprintf (stderr, "symbol %s %s in ", sp->name, reftype);        fprintf (stderr, "symbol %s %s in ", sp->name, reftype);
Line 1998  contains_symbol (entry, n_ptr) Line 2444  contains_symbol (entry, n_ptr)
 {  {
   if (n_ptr >= entry->symbols &&    if (n_ptr >= entry->symbols &&
       n_ptr < (entry->symbols        n_ptr < (entry->symbols
                + (entry->header.a_syms / sizeof (struct nlist))))                 + (entry->syms_size / sizeof (struct nlist))))
     return (unsigned long) entry;      return (unsigned long) entry;
   return 0;    return 0;
 }  }
Line 2061  decode_library_subfile (desc, library_en Line 2507  decode_library_subfile (desc, library_en
   
   lseek (desc, subfile_offset, 0);    lseek (desc, subfile_offset, 0);
   
   #ifdef LARMAG
     bytes_read = getarhdr (desc, &hdr1);
   #else
   bytes_read = read (desc, &hdr1, sizeof hdr1);    bytes_read = read (desc, &hdr1, sizeof hdr1);
   #endif
   
   if (!bytes_read)    if (!bytes_read)
     return 0;           /* end of archive */      return 0;           /* end of archive */
   
   #ifdef LARMAG
     if (bytes_read < 0)
   #else
   if (sizeof hdr1 != bytes_read)    if (sizeof hdr1 != bytes_read)
   #endif
     fatal_with_file ("malformed library archive ", library_entry);      fatal_with_file ("malformed library archive ", library_entry);
   
   if (sscanf (hdr1.ar_size, "%d", &member_length) != 1)    if (sscanf (hdr1.ar_size, "%d", &member_length) != 1)
Line 2074  decode_library_subfile (desc, library_en Line 2529  decode_library_subfile (desc, library_en
   subentry = (struct file_entry *) xmalloc (sizeof (struct file_entry));    subentry = (struct file_entry *) xmalloc (sizeof (struct file_entry));
   bzero (subentry, sizeof (struct file_entry));    bzero (subentry, sizeof (struct file_entry));
   
   #ifdef LARMAG
     namelen = strlen (hdr1.ar_name);
   #else
   for (namelen = 0;    for (namelen = 0;
        namelen < sizeof hdr1.ar_name         namelen < sizeof hdr1.ar_name
        && hdr1.ar_name[namelen] != 0 && hdr1.ar_name[namelen] != ' '         && hdr1.ar_name[namelen] != 0 && hdr1.ar_name[namelen] != ' '
        && hdr1.ar_name[namelen] != '/';         && hdr1.ar_name[namelen] != '/';
        namelen++);         namelen++);
   #endif
   
   name = (char *) xmalloc (namelen+1);    name = (char *) xmalloc (namelen+1);
   strncpy (name, hdr1.ar_name, namelen);    strncpy (name, hdr1.ar_name, namelen);
Line 2089  decode_library_subfile (desc, library_en Line 2548  decode_library_subfile (desc, library_en
   subentry->symbols = 0;    subentry->symbols = 0;
   subentry->strings = 0;    subentry->strings = 0;
   subentry->subfiles = 0;    subentry->subfiles = 0;
   #ifdef LARMAG
     /* The struct ar_hdr is packed in the file */
     /* The return value of getarhdr accounts for just part of it */
     bytes_read += sizeof hdr1 - sizeof hdr1.ar_name;
     subentry->starting_offset = subfile_offset + bytes_read;
   #else
   subentry->starting_offset = subfile_offset + sizeof hdr1;    subentry->starting_offset = subfile_offset + sizeof hdr1;
   #endif
   subentry->superfile = library_entry;    subentry->superfile = library_entry;
   subentry->library_flag = 0;    subentry->library_flag = 0;
   subentry->header_read_flag = 0;    subentry->header_read_flag = 0;
Line 2205  symdef_library (desc, entry, member_leng Line 2671  symdef_library (desc, entry, member_leng
                          + symdef_base[i].symbol_name_string_index,                           + symdef_base[i].symbol_name_string_index,
                          entry->filename);                           entry->filename);
                 read_entry_symbols (desc, subentry);                  read_entry_symbols (desc, subentry);
                 subentry->strings = (char *) malloc (subentry->string_size);                  subentry->strings = xmalloc (subentry->strs_size);
                 read_entry_strings (desc, subentry);                  read_entry_strings (desc, subentry);
   
                 /* Now scan the symbol table and decide whether to load.  */                  /* Now scan the symbol table and decide whether to load.  */
Line 2213  symdef_library (desc, entry, member_leng Line 2679  symdef_library (desc, entry, member_leng
                 if (!subfile_wanted_p (subentry))                  if (!subfile_wanted_p (subentry))
                   {                    {
                     free (subentry->symbols);                      free (subentry->symbols);
                       free (subentry->strings);
                     free (subentry);                      free (subentry);
                   }                    }
                 else                  else
Line 2238  symdef_library (desc, entry, member_leng Line 2705  symdef_library (desc, entry, member_leng
                         if (symdef_base[j].library_member_offset == offset)                          if (symdef_base[j].library_member_offset == offset)
                           symdef_base[j].symbol_name_string_index = -1;                            symdef_base[j].symbol_name_string_index = -1;
                       }                        }
                   }  
   
                 /* We'll read the strings again if we need them again.  */                      /* We'll read the strings again if we need them again.  */
                 free (subentry->strings);                      free (subentry->strings);
                 subentry->strings = 0;                      subentry->strings = 0;
                     }
               }                }
           }            }
     }      }
Line 2258  process_subentry (desc, subentry, entry, Line 2725  process_subentry (desc, subentry, entry,
      register struct file_entry *subentry;       register struct file_entry *subentry;
      struct file_entry **prev_addr, *entry;       struct file_entry **prev_addr, *entry;
 {  {
   register struct file_entry *prev = *prev_addr;  
   
   read_entry_symbols (desc, subentry);    read_entry_symbols (desc, subentry);
   subentry->strings = (char *) alloca (subentry->string_size);    subentry->strings = (char *) alloca (subentry->strs_size);
   read_entry_strings (desc, subentry);    read_entry_strings (desc, subentry);
   
   if (!subfile_wanted_p (subentry))    if (!subfile_wanted_p (subentry))
Line 2273  process_subentry (desc, subentry, entry, Line 2738  process_subentry (desc, subentry, entry,
     {      {
       enter_file_symbols (subentry);        enter_file_symbols (subentry);
   
       if (prev)        if (*prev_addr)
         prev->chain = subentry;          (*prev_addr)->chain = subentry;
       else        else
         entry->subfiles = subentry;          entry->subfiles = subentry;
       prev = subentry;        *prev_addr = subentry;
       subentry->strings = 0; /* Since space will dissapear on return */        subentry->strings = 0; /* Since space will dissapear on return */
     }      }
 }  }
Line 2304  linear_library (desc, entry) Line 2769  linear_library (desc, entry)
       if (!subentry) return;        if (!subentry) return;
   
       process_subentry (desc, subentry, entry, &prev);        process_subentry (desc, subentry, entry, &prev);
   #ifdef LARMAG
         this_subfile_offset = member_length + subentry->starting_offset;
   #else
       this_subfile_offset += member_length + sizeof (struct ar_hdr);        this_subfile_offset += member_length + sizeof (struct ar_hdr);
   #endif
       if (this_subfile_offset & 1) this_subfile_offset++;        if (this_subfile_offset & 1) this_subfile_offset++;
     }      }
 }  }
Line 2319  subfile_wanted_p (entry) Line 2788  subfile_wanted_p (entry)
 {  {
   register struct nlist *p;    register struct nlist *p;
   register struct nlist *end    register struct nlist *end
     = entry->symbols + entry->header.a_syms / sizeof (struct nlist);      = entry->symbols + entry->syms_size / sizeof (struct nlist);
 #ifdef DOLLAR_KLUDGE  #ifdef DOLLAR_KLUDGE
   register int dollar_cond = 0;    register int dollar_cond = 0;
 #endif  #endif
Line 2333  subfile_wanted_p (entry) Line 2802  subfile_wanted_p (entry)
          potentially want it.  */           potentially want it.  */
       if (type & N_EXT        if (type & N_EXT
           && (type != (N_UNDF | N_EXT) || p->n_value            && (type != (N_UNDF | N_EXT) || p->n_value
                 
 #ifdef DOLLAR_KLUDGE  #ifdef DOLLAR_KLUDGE
                || name[1] == '$'                 || name[1] == '$'
 #endif  #endif
Line 2366  subfile_wanted_p (entry) Line 2835  subfile_wanted_p (entry)
   
           if (!sp) continue;            if (!sp) continue;
   
           if ((sp->referenced && !sp->defined)            /* Note: There has been a lot of discussion about what to
               || (sp->defined && sp->max_common_size))               when a common definition was previously seen (i.e. when
                sp->max_common_size > 0).
                The latest solution is to treat a previous common definition
                (wrt to subfile_wanted_p) no differently from a real definition.
                This has the advantage of simplicity and consistency: a common
                definition is just like a common definition (consistent
                with strict ANSI C) except that we allow duplicate definitions.
                Possible disadvantage: May not be the best choice for Fortran,
                though it is consistent with the standard.
   
                An earlier solution:
                We wanted to see a common definition in the subfile,
                and note its size, but ignore any other definition
                if the symbol was already defined (even as a common).
                This meant that if there were multiple common definitions,
                the final definition would use the largest size of any of them,
                as it should.  But if there was a common definition and another
                definition, like "int pipe;" in a program and "int pipe() {}"
                in the library, only the common would be used.
                Disadvantage: a poorly justified kludge.
   
                Another previous solution:
                If the symbol already had a definition as a common symbol,
                we would want this subfile if some other subfile of the
                same library that we already need anyway also used the symbol.
                This seemed like an even more ad hoc decision.
                It would also cause subfiles to be pulled in that would
                then conflict with previous entries. I.e. you couldn't
                have: ld ... start.o libc.a ... if libc.a contained start.o.
   
                Other hybrid solutions were also considered.
             */
             if ((sp->referenced && !sp->defined))
             {              {
               /* This is a symbol we are looking for.  It is either  
                  not yet defined or defined as a common.  */  
 #ifdef DOLLAR_KLUDGE  #ifdef DOLLAR_KLUDGE
               if (dollar_cond) continue;                if (dollar_cond) continue;
 #endif  #endif
Line 2379  subfile_wanted_p (entry) Line 2878  subfile_wanted_p (entry)
                   /* Symbol being defined as common.                    /* Symbol being defined as common.
                      Remember this, but don't load subfile just for this.  */                       Remember this, but don't load subfile just for this.  */
   
                   /* If it didn't used to be common, up the count of                    common_defined_global_count++;
                      common symbols.  */                    sp->max_common_size = p->n_value;
                   if (!sp->max_common_size)                    undefined_global_sym_count--;
                     common_defined_global_count++;  
   
                   if (sp->max_common_size < p->n_value)  
                     sp->max_common_size = p->n_value;  
                   if (!sp->defined)  
                     undefined_global_sym_count--;  
                   sp->defined = 1;                    sp->defined = 1;
                   continue;                    continue;
                 }                  }
   
               if (write_map)                if (write_map)
                 {                  {
                   print_file_name (entry, stdout);                    print_file_name (entry, stdout);
Line 2423  digest_symbols () Line 2915  digest_symbols ()
   if (trace_files)    if (trace_files)
     fprintf (stderr, "Digesting symbol information:\n\n");      fprintf (stderr, "Digesting symbol information:\n\n");
   
     /* Initialize the text_start address; this depends on the output file formats.  */
   
     initialize_text_start ();
   
     text_size = text_header_size;
   
   /* Compute total size of sections */    /* Compute total size of sections */
   
   each_file (consider_file_section_lengths, 0);    each_file (consider_file_section_lengths, 0);
Line 2430  digest_symbols () Line 2928  digest_symbols ()
   /* If necessary, pad text section to full page in the file.    /* If necessary, pad text section to full page in the file.
      Include the padding in the text segment size.  */       Include the padding in the text segment size.  */
   
 #ifdef NMAGIC    if (output_style == OUTPUT_READONLY_TEXT || output_style == OUTPUT_DEMAND_PAGED)
   if (magic == ZMAGIC || magic == NMAGIC)      {
   #ifdef tek4300
         int page_size = ZMALIGN; /* a lie */
   #endif
   #ifdef is68k
         text_pad = ((text_size + SEGMENT_SIZE - 1) & (- SEGMENT_SIZE) - text_size;
 #else  #else
   if (magic == ZMAGIC)        text_pad = ((text_size + page_size - 1) & (- page_size)) - text_size;
 #endif  #endif
     {  
       int text_end = text_size + N_TXTOFF (outheader);  
       text_pad = ((text_end + page_size - 1) & (- page_size)) - text_end;  
       text_size += text_pad;        text_size += text_pad;
     }      }
   
   outheader.a_text = text_size;    /* Now that the text_size is known, initialize the data start address;
 #ifdef sequent       this depends on text_size as well as the output file format.  */
   outheader.a_text += N_ADDRADJ (outheader);  
 #endif  
   
   /* Make the data segment address start in memory on a suitable boundary.  */  
   
   if (! Tdata_flag_specified)  
     data_start = N_DATADDR (outheader) + text_start - N_TXTADDR (outheader);  
   
   /* Make sure bss starts out aligned as much as anyone can want.  */  
   
   data_size = (data_size + sizeof(double) - 1) & ~(sizeof(double)-1);    initialize_data_start ();
   
   /* Set up the set element vector */    /* Set up the set element vector */
   
   if (!relocatable_output)    if (output_style != OUTPUT_RELOCATABLE)
     {      {
       /* The set sector size is the number of set elements + a word        /* The set sector size is the number of set elements + a word
          for each symbol for the length word at the beginning of the           for each symbol for the length word at the beginning of the
Line 2471  digest_symbols () Line 2962  digest_symbols ()
       setv_fill_count = 0;        setv_fill_count = 0;
     }      }
   
     /* Make sure bss starts out aligned as much as anyone can want.  */
     {
       int new_data_size = (data_size + sizeof(double) - 1) & ~(sizeof(double)-1);
   
       data_pad += new_data_size - data_size;
       data_size = new_data_size;
     }
   
   /* Compute start addresses of each file's sections and symbols.  */    /* Compute start addresses of each file's sections and symbols.  */
   
   each_full_file (relocate_file_addresses, 0);    each_full_file (relocate_file_addresses, 0);
Line 2493  digest_symbols () Line 2992  digest_symbols ()
         {          {
           /* For each symbol */            /* For each symbol */
           register struct nlist *p, *next;            register struct nlist *p, *next;
           int defs = 0, com = sp->max_common_size, erred = 0;            int defs = 0, com = sp->max_common_size;
           struct nlist *first_definition;            struct nlist *first_definition;
           for (p = sp->refs; p; p = next)            for (p = sp->refs; p; p = next)
             {              {
Line 2501  digest_symbols () Line 3000  digest_symbols ()
   
               if (SET_ELEMENT_P (type))                if (SET_ELEMENT_P (type))
                 {                  {
                   if (relocatable_output)                    if (output_style == OUTPUT_RELOCATABLE)
                     fatal ("internal: global ref to set element with -r");                      fatal ("internal: global ref to set element with -r");
                   if (!defs++)                    if (!defs++)
                     {                      {
Line 2535  digest_symbols () Line 3034  digest_symbols ()
           /* Allocate as common if defined as common and not defined for real */            /* Allocate as common if defined as common and not defined for real */
           if (com && !defs)            if (com && !defs)
             {              {
               if (!relocatable_output || force_common_definition)                if (output_style != OUTPUT_RELOCATABLE || force_common_definition)
                 {                  {
                   int align = sizeof (int);                    int align = sizeof (int);
   
Line 2546  digest_symbols () Line 3045  digest_symbols ()
                      this size alignment is ever removed, ALIGN above                       this size alignment is ever removed, ALIGN above
                      will have to be initialized to 1 instead of                       will have to be initialized to 1 instead of
                      sizeof (int).  */                       sizeof (int).  */
                     
                   com = (com + sizeof (int) - 1) & (- sizeof (int));                    com = (com + sizeof (int) - 1) & (- sizeof (int));
   
                   while (!(com & align))                    while (!(com & align))
Line 2604  digest_symbols () Line 3103  digest_symbols ()
   
   bss_size = (bss_size + sizeof(double) - 1) & ~(sizeof(double)-1);    bss_size = (bss_size + sizeof(double) - 1) & ~(sizeof(double)-1);
   
   if (end_symbol)               /* These are null if -r.  */    /* Give values to _end and friends.  */
     {    {
       etext_symbol->value = text_size + text_start;      int end_value = data_start + data_size + bss_size;
       edata_symbol->value = data_start + data_size;      if (end_symbol)
       end_symbol->value = data_start + data_size + bss_size;        end_symbol->value = end_value;
     }      if (end_symbol_alt)
         end_symbol_alt->value = end_value;
     }
   
     {
       int etext_value = text_size + text_start;
       if (etext_symbol)
         etext_symbol->value = etext_value;
       if (etext_symbol_alt)
         etext_symbol_alt->value = etext_value;
     }
   
     {
       int edata_value = data_start + data_size;
       if (edata_symbol)
         edata_symbol->value = edata_value;
       if (edata_symbol_alt)
         edata_symbol_alt->value = edata_value;
     }
   
   /* Figure the data_pad now, so that it overlaps with the bss addresses.  */    /* Figure the data_pad now, so that it overlaps with the bss addresses.  */
   
   if (specified_data_size && specified_data_size > data_size)    {
     data_pad = specified_data_size - data_size;      /* The amount of data_pad that we are computing now.  This is the
          part which overlaps with bss.  What was computed previously
          goes before bss.  */
       int data_pad_additional = 0;
       
       if (specified_data_size && specified_data_size > data_size)
         data_pad_additional = specified_data_size - data_size;
   
       if (output_style == OUTPUT_DEMAND_PAGED)
         data_pad_additional =
           ((data_pad_additional + data_size + page_size - 1) & (- page_size)) - data_size;
   
   if (magic == ZMAGIC)      bss_size -= data_pad_additional;
     data_pad = ((data_pad + data_size + page_size - 1) & (- page_size))      if (bss_size < 0) bss_size = 0;
                - data_size;  
   
   bss_size -= data_pad;      data_size += data_pad_additional;
   if (bss_size < 0) bss_size = 0;  
   
   data_size += data_pad;      data_pad += data_pad_additional;
     }
 }  }
   
 /* Accumulate the section sizes of input file ENTRY  /* Accumulate the section sizes of input file ENTRY
Line 2638  consider_file_section_lengths (entry) Line 3164  consider_file_section_lengths (entry)
   
   entry->text_start_address = text_size;    entry->text_start_address = text_size;
   /* If there were any vectors, we need to chop them off */    /* If there were any vectors, we need to chop them off */
   text_size += entry->header.a_text;    text_size += entry->text_size;
   entry->data_start_address = data_size;    entry->data_start_address = data_size;
   data_size += entry->header.a_data;    data_size += entry->data_size;
   entry->bss_start_address = bss_size;    entry->bss_start_address = bss_size;
   bss_size += entry->header.a_bss;    bss_size += entry->bss_size;
   
   text_reloc_size += entry->header.a_trsize;    text_reloc_size += entry->text_reloc_size;
   data_reloc_size += entry->header.a_drsize;    data_reloc_size += entry->data_reloc_size;
 }  }
   
 /* Determine where the sections of ENTRY go into the output file,  /* Determine where the sections of ENTRY go into the output file,
Line 2657  relocate_file_addresses (entry) Line 3183  relocate_file_addresses (entry)
      register struct file_entry *entry;       register struct file_entry *entry;
 {  {
   entry->text_start_address += text_start;    entry->text_start_address += text_start;
   /* Note that `data_start' and `data_size' have not yet been  
      adjusted for `data_pad'.  If they had been, we would get the wrong    /* Note that `data_start' and `data_size' have not yet been adjusted
      results here.  */       for the portion of data_pad which overlaps with bss.  If they had
        been, we would get the wrong results here.  */
   entry->data_start_address += data_start;    entry->data_start_address += data_start;
   entry->bss_start_address += data_start + data_size;    entry->bss_start_address += data_start + data_size;
   
   {    {
     register struct nlist *p;      register struct nlist *p;
     register struct nlist *end      register struct nlist *end
       = entry->symbols + entry->header.a_syms / sizeof (struct nlist);        = entry->symbols + entry->syms_size / sizeof (struct nlist);
   
     for (p = entry->symbols; p < end; p++)      for (p = entry->symbols; p < end; p++)
       {        {
Line 2677  relocate_file_addresses (entry) Line 3204  relocate_file_addresses (entry)
           {            {
           case N_TEXT:            case N_TEXT:
           case N_SETT:            case N_SETT:
             p->n_value += entry->text_start_address;              p->n_value += entry->text_start_address - entry->orig_text_address;
             break;              break;
           case N_DATA:            case N_DATA:
           case N_SETV:            case N_SETV:
           case N_SETD:            case N_SETD:
             /* A symbol whose value is in the data section              /* Data segment symbol.  Subtract the address of the
                is present in the input file as if the data section                 data segment in the input file, and add the address
                started at an address equal to the length of the file's text.  */                 of this input file's data segment in the output file.  */
             p->n_value += entry->data_start_address - entry->header.a_text;              p->n_value +=
                 entry->data_start_address - entry->orig_data_address;
             break;              break;
           case N_BSS:            case N_BSS:
           case N_SETB:            case N_SETB:
             /* likewise for symbols with value in BSS.  */              /* likewise for symbols with value in BSS.  */
             p->n_value += entry->bss_start_address              p->n_value += entry->bss_start_address - entry->orig_bss_address;
               - entry->header.a_text - entry->header.a_data;  
             break;              break;
           }            }
       }        }
Line 2742  describe_file_sections (entry, outfile) Line 3269  describe_file_sections (entry, outfile)
     fprintf (outfile, " symbols only\n", 0);      fprintf (outfile, " symbols only\n", 0);
   else    else
     fprintf (outfile, " text %x(%x), data %x(%x), bss %x(%x) hex\n",      fprintf (outfile, " text %x(%x), data %x(%x), bss %x(%x) hex\n",
              entry->text_start_address, entry->header.a_text,               entry->text_start_address, entry->text_size,
              entry->data_start_address, entry->header.a_data,               entry->data_start_address, entry->data_size,
              entry->bss_start_address, entry->header.a_bss);               entry->bss_start_address, entry->bss_size);
 }  }
   
 void  void
Line 2754  list_file_locals (entry, outfile) Line 3281  list_file_locals (entry, outfile)
 {  {
   register struct nlist    register struct nlist
     *p,      *p,
     *end = entry->symbols + entry->header.a_syms / sizeof (struct nlist);      *end = entry->symbols + entry->syms_size / sizeof (struct nlist);
   
   entry->strings = (char *) alloca (entry->string_size);    entry->strings = (char *) alloca (entry->strs_size);
   read_entry_strings (file_open (entry), entry);    read_entry_strings (file_open (entry), entry);
   
   fprintf (outfile, "\nLocal symbols of ");    fprintf (outfile, "\nLocal symbols of ");
Line 2831  next_debug_entry (use_data_symbols, stat Line 3358  next_debug_entry (use_data_symbols, stat
   current->filename = next->filename;    current->filename = next->filename;
   
   while (++(next->sym) < (entry->symbols    while (++(next->sym) < (entry->symbols
                           + entry->header.a_syms/sizeof (struct nlist)))                            + entry->syms_size/sizeof (struct nlist)))
     {      {
       /* n_type is a char, and N_SOL, N_EINCL and N_BINCL are > 0x80, so        /* n_type is a char, and N_SOL, N_EINCL and N_BINCL are > 0x80, so
        * may look negative...therefore, must mask to low bits         * may look negative...therefore, must mask to low bits
        */         */
       switch (next->sym->n_type & 0xff)         switch (next->sym->n_type & 0xff)
         {          {
         case N_SLINE:          case N_SLINE:
           if (use_data_symbols) continue;            if (use_data_symbols) continue;
Line 2891  init_debug_scan (use_data_symbols, entry Line 3418  init_debug_scan (use_data_symbols, entry
   
   for (tmp = entry->symbols;    for (tmp = entry->symbols;
        tmp < (entry->symbols         tmp < (entry->symbols
               + entry->header.a_syms/sizeof (struct nlist));                + entry->syms_size/sizeof (struct nlist));
        tmp++)         tmp++)
     if (tmp->n_type == (int) N_SO)      if (tmp->n_type == (int) N_SO)
       break;        break;
   
   if (tmp >= (entry->symbols    if (tmp >= (entry->symbols
               + entry->header.a_syms/sizeof (struct nlist)))                + entry->syms_size/sizeof (struct nlist)))
     {      {
       /* I believe this translates to "We lose" */        /* I believe this translates to "We lose" */
       current->filename = next->filename = entry->filename;        current->filename = next->filename = entry->filename;
Line 2940  init_debug_scan (use_data_symbols, entry Line 3467  init_debug_scan (use_data_symbols, entry
    which describes the current location in the implied scan through     which describes the current location in the implied scan through
    the debug symbols within the file which ADDRESS is within, and     the debug symbols within the file which ADDRESS is within, and
    returns the source line number which corresponds to ADDRESS.  */     returns the source line number which corresponds to ADDRESS.  */
     
 int  int
 address_to_line (address, state_pointer)  address_to_line (address, state_pointer)
      unsigned long address;       unsigned long address;
Line 2955  address_to_line (address, state_pointer) Line 3482  address_to_line (address, state_pointer)
   int use_data_symbols;    int use_data_symbols;
   
   if (next->sym)    if (next->sym)
     use_data_symbols = (next->sym->n_type & N_TYPE) == N_DATA;      use_data_symbols = (next->sym->n_type & ~N_EXT) == N_DATA;
   else    else
     return current->line;      return current->line;
   
Line 3006  do_relocation_warnings (entry, data_segm Line 3533  do_relocation_warnings (entry, data_segm
   struct relocation_info    struct relocation_info
     *reloc_start = data_segment ? entry->datarel : entry->textrel,      *reloc_start = data_segment ? entry->datarel : entry->textrel,
     *reloc;      *reloc;
     long syms_size = entry->syms_size / sizeof (struct nlist);
   int reloc_size    int reloc_size
     = ((data_segment ? entry->header.a_drsize : entry->header.a_trsize)      = ((data_segment ? entry->data_reloc_size : entry->text_reloc_size)
        / sizeof (struct relocation_info));         / sizeof (struct relocation_info));
   int start_of_segment    int start_of_segment
     = (data_segment ? entry->data_start_address : entry->text_start_address);      = (data_segment ? entry->data_start_address : entry->text_start_address);
   struct nlist *start_of_syms = entry->symbols;    struct nlist *start_of_syms = entry->symbols;
   struct line_debug_entry *state_pointer    struct line_debug_entry *state_pointer
     = init_debug_scan (data_segment != 0, entry);      = init_debug_scan (data_segment != 0, entry);
   register struct line_debug_entry    register struct line_debug_entry *current = state_pointer;
     *current = state_pointer,  
     *next = state_pointer + 1,  
     *source = state_pointer + 2;  
   /* Assigned to generally static values; should not be written into.  */    /* Assigned to generally static values; should not be written into.  */
   char *errfmt;    char *errfmt;
   /* Assigned to alloca'd values cand copied into; should be freed    /* Assigned to alloca'd values cand copied into; should be freed
Line 3037  do_relocation_warnings (entry, data_segm Line 3562  do_relocation_warnings (entry, data_segm
     {      {
       register struct nlist *s;        register struct nlist *s;
       register symbol *g;        register symbol *g;
         int s_index;
   
       /* If the relocation isn't resolved through a symbol, continue */        /* If the relocation isn't resolved through a symbol, continue */
       if (!RELOC_EXTERN_P(reloc))        if (!RELOC_EXTERN_P(reloc))
         continue;          continue;
   
       s = &(entry->symbols[RELOC_SYMBOL(reloc)]);        s_index = RELOC_SYMBOL(reloc);
         if (s_index < 0 || s_index >= syms_size)
           fatal_with_file ("bad symbol in relocation table of ", entry);
         s = &entry->symbols[s_index];
   
       /* Local symbols shouldn't ever be used by relocation info, so        /* Local symbols shouldn't ever be used by relocation info, so
          the next should be safe.           the next should be safe.
Line 3061  do_relocation_warnings (entry, data_segm Line 3590  do_relocation_warnings (entry, data_segm
         {          {
           /* Mark as being noted by relocation warning pass.  */            /* Mark as being noted by relocation warning pass.  */
           SET_BIT (nlist_bitvector, s - start_of_syms);            SET_BIT (nlist_bitvector, s - start_of_syms);
             
           if (g->undef_refs >= MAX_UREFS_PRINTED)    /* Listed too many */            if (g->undef_refs >= MAX_UREFS_PRINTED)    /* Listed too many */
             continue;              continue;
   
Line 3085  do_relocation_warnings (entry, data_segm Line 3614  do_relocation_warnings (entry, data_segm
   
           /* Mark as being noted by relocation warning pass.  */            /* Mark as being noted by relocation warning pass.  */
           SET_BIT (nlist_bitvector, s - start_of_syms);            SET_BIT (nlist_bitvector, s - start_of_syms);
             
           errfmt = 0;            errfmt = 0;
           errmsg = g->warning;            errmsg = g->warning;
           invalidate_line_number = 0;            invalidate_line_number = 0;
         }          }
         
   
       /* If errfmt == 0, errmsg has already been defined.  */        /* If errfmt == 0, errmsg has already been defined.  */
       if (errfmt != 0)        if (errfmt != 0)
         {          {
           errmsg = (char *) xmalloc (strlen (errfmt) + strlen (g->name) + 1);            char *nm;
           sprintf (errmsg, errfmt, g->name, data_segment ? "data" : "text");  
             if (!demangler || !(nm = (*demangler)(g->name)))
               nm = g->name;
             errmsg = xmalloc (strlen (errfmt) + strlen (nm) + 1);
             sprintf (errmsg, errfmt, nm, data_segment ? "data" : "text");
             if (nm != g->name)
               free (nm);
         }          }
   
       address_to_line (RELOC_ADDRESS (reloc) + start_of_segment,        address_to_line (RELOC_ADDRESS (reloc) + start_of_segment,
                        state_pointer);                         state_pointer);
   
       if (current->line >=0)        if (current->line >=0)
         fprintf (outfile, "%s:%d: %s\n", current->filename,          {
                  invalidate_line_number ? 0 : current->line, errmsg);            fprintf (outfile, "%s:%d (", current->filename,
                      invalidate_line_number ? 0 : current->line);
             print_file_name (entry, outfile);
             fprintf (outfile, "): %s\n", errmsg);
           }
       else        else
         fprintf (outfile, "%s: %s\n", current->filename, errmsg);          {
             print_file_name(entry, outfile);
             fprintf(outfile, ": %s\n", errmsg);
           }
   
       if (errfmt != 0)        if (errfmt != 0)
         free (errmsg);          free (errmsg);
Line 3124  do_file_warnings (entry, outfile) Line 3666  do_file_warnings (entry, outfile)
      struct file_entry *entry;       struct file_entry *entry;
      FILE *outfile;       FILE *outfile;
 {  {
   int number_of_syms = entry->header.a_syms / sizeof (struct nlist);    int number_of_syms = entry->syms_size / sizeof (struct nlist);
   unsigned char *nlist_bitvector    unsigned char *nlist_bitvector
     = (unsigned char *) alloca ((number_of_syms >> 3) + 1);      = (unsigned char *) alloca ((number_of_syms >> 3) + 1);
   struct line_debug_entry *text_scan, *data_scan;    struct line_debug_entry *text_scan, *data_scan;
Line 3140  do_file_warnings (entry, outfile) Line 3682  do_file_warnings (entry, outfile)
     {      {
       int desc;        int desc;
   
       entry->strings = (char *) alloca (entry->string_size);        entry->strings = (char *) alloca (entry->strs_size);
       desc = file_open (entry);        desc = file_open (entry);
       read_entry_strings (desc, entry);        read_entry_strings (desc, entry);
     }      }
Line 3177  do_file_warnings (entry, outfile) Line 3719  do_file_warnings (entry, outfile)
           errfmt = "Definition of symbol %s (multiply defined)";            errfmt = "Definition of symbol %s (multiply defined)";
           switch (s->n_type)            switch (s->n_type)
             {              {
               case N_ABS | N_EXT:
                 line_number = -1;
                 break;
             case N_TEXT | N_EXT:              case N_TEXT | N_EXT:
               line_number = address_to_line (s->n_value, text_scan);                line_number = address_to_line (s->n_value, text_scan);
               file_name = text_scan[0].filename;                file_name = text_scan[0].filename;
Line 3204  do_file_warnings (entry, outfile) Line 3749  do_file_warnings (entry, outfile)
         {          {
           if (g->undef_refs >= MAX_UREFS_PRINTED)            if (g->undef_refs >= MAX_UREFS_PRINTED)
             continue;              continue;
             
           if (++(g->undef_refs) == MAX_UREFS_PRINTED)            if (++(g->undef_refs) == MAX_UREFS_PRINTED)
             errfmt = "More undefined \"%s\" refs follow";              errfmt = "More undefined \"%s\" refs follow";
           else            else
Line 3227  do_file_warnings (entry, outfile) Line 3772  do_file_warnings (entry, outfile)
         }          }
       else        else
         continue;          continue;
         
       if (line_number == -1)        if (line_number == -1)
         fprintf (outfile, "%s: ", entry->filename);          {
             print_file_name (entry, outfile);
             fprintf (outfile, ": ");
           }
       else        else
         fprintf (outfile, "%s:%d: ", file_name, line_number);          {
             fprintf (outfile, "%s:%d (", file_name, line_number);
             print_file_name (entry, outfile);
             fprintf (outfile, "): ");
           }
   
       if (dont_allow_symbol_name)        if (dont_allow_symbol_name)
         fprintf (outfile, "%s", errfmt);          fprintf (outfile, "%s", errfmt);
       else        else
         fprintf (outfile, errfmt, g->name);          {
             char *nm;
   
             if (!demangler || !(nm = (*demangler)(g->name)))
               fprintf (outfile, errfmt, g->name);
             else
               {
                 fprintf (outfile, errfmt, nm);
                 free (nm);
               }
           }
   
       fputc ('\n', outfile);        fputc ('\n', outfile);
     }      }
Line 3248  do_file_warnings (entry, outfile) Line 3810  do_file_warnings (entry, outfile)
 do_warnings (outfile)  do_warnings (outfile)
      FILE *outfile;       FILE *outfile;
 {  {
   int i;    list_unresolved_refs = output_style != OUTPUT_RELOCATABLE && undefined_global_sym_count;
   
   list_unresolved_refs = !relocatable_output && undefined_global_sym_count;  
   list_warning_symbols = warning_count;    list_warning_symbols = warning_count;
   list_multiple_defs = multiple_def_count != 0;    list_multiple_defs = multiple_def_count != 0;
   
Line 3262  do_warnings (outfile) Line 3822  do_warnings (outfile)
   
   each_file (do_file_warnings, outfile);    each_file (do_file_warnings, outfile);
   
     if (entry_symbol && !entry_symbol->defined) 
       fprintf(stderr, "%s: error: Entry symbol `%s' never defined.\n",
               progname, entry_symbol->name);
   
   if (list_unresolved_refs || list_multiple_defs)    if (list_unresolved_refs || list_multiple_defs)
     make_executable = 0;      make_executable = 0;
 }  }
   
 /* Write the output file */  #ifdef A_OUT
   
 void  
 write_output ()  
 {  
   struct stat statbuf;  
   int filemode;  
   
   outdesc = open (output_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);  /* Stuff pertaining to creating a.out files. */
   if (outdesc < 0) perror_name (output_filename);  
   
   if (fstat (outdesc, &statbuf) < 0)  /* The a.out header. */
     perror_name (output_filename);  
   
   filemode = statbuf.st_mode;  #ifdef tek4300
   struct zexec outheader;
   #else
   struct exec outheader;
   #endif
   
   chmod (output_filename, filemode & ~0111);  #ifdef COFF_ENCAPSULATE
   int need_coff_header;
   struct coffheader coffheader;
   #endif
   
   /* Output the a.out header.  */  /* Compute text_start and text_header_size for an a.out file.  */
   write_header ();  
   
   /* Output the text and data segments, relocating as we go.  */  void
   write_text ();  initialize_a_out_text_start ()
   write_data ();  {
     int magic;
   
   /* Output the merged relocation info, if requested with `-r'.  */    switch (output_style)
   if (relocatable_output)      {
     write_rel ();      case OUTPUT_RELOCATABLE:
       case OUTPUT_WRITABLE_TEXT:
         magic = OMAGIC;
         break;
       case OUTPUT_READONLY_TEXT:
   #ifdef NMAGIC
         magic = NMAGIC;
         break;
   #endif
       case OUTPUT_DEMAND_PAGED:
         magic = ZMAGIC;
         break;
       default:
         fatal ("unknown output style found (bug in ld)", (char *) 0);
         break;
       }
   
   /* Output the symbol table (both globals and locals).  */    /* Determine whether to count the header as part of
   write_syms ();       the text size, and initialize the text size accordingly.
        This depends on the kind of system and on the output format selected.  */
     N_SET_MAGIC (outheader, magic);
   #ifdef INITIALIZE_HEADER
     INITIALIZE_HEADER;
   #endif
   
   /* Copy any GDB symbol segments from input files.  */    text_header_size = sizeof (struct exec);
   write_symsegs ();  #ifdef COFF_ENCAPSULATE
     /* Don't write the coff header for the output of ld -A (since
        it is not executable by the kernel anyway).  */
     if (output_style != OUTPUT_RELOCATABLE && !file_table[0].just_syms_flag)
       {
         need_coff_header = 1;
         /* set this flag now, since it will change the values of N_TXTOFF, etc */
         N_SET_FLAGS (outheader, N_FLAGS_COFF_ENCAPSULATE);
         text_header_size += sizeof (struct coffheader);
       }
   #endif
     if (text_header_size <= N_TXTOFF (outheader))
       text_header_size = 0;
     else
       text_header_size -= N_TXTOFF (outheader);
   
   close (outdesc);  #ifdef _N_BASEADDR
     /* SunOS 4.1 N_TXTADDR depends on the value of outheader.a_entry. */
     outheader.a_entry = N_PAGSIZ(outheader);
   #endif
   
   if (chmod (output_filename, filemode | 0111) == -1)    if (!T_flag_specified && output_style != OUTPUT_RELOCATABLE)
     perror_name (output_filename);      text_start = N_TXTADDR (outheader);
 }  }
   
 void modify_location (), perform_relocation (), copy_text (), copy_data ();  /* Compute data_start once text_size is known. */
   
 void  void
 write_header ()  initialize_a_out_data_start ()
 {  {
   N_SET_MAGIC (outheader, magic);  
   outheader.a_text = text_size;    outheader.a_text = text_size;
 #ifdef sequent  #ifdef sequent
   outheader.a_text += N_ADDRADJ (outheader);    outheader.a_text += N_ADDRADJ (outheader);
     if (entry_symbol == 0)
       entry_symbol = getsym ("start");
 #endif  #endif
     if (! Tdata_flag_specified)
       data_start = N_DATADDR (outheader) + text_start - N_TXTADDR (outheader);
   }
   
   /* Compute offsets of various pieces of the a.out output file.  */
   
   void
   compute_a_out_section_offsets ()
   {
   outheader.a_data = data_size;    outheader.a_data = data_size;
   outheader.a_bss = bss_size;    outheader.a_bss = bss_size;
   outheader.a_entry = (entry_symbol ? entry_symbol->value    outheader.a_entry = (entry_symbol ? entry_symbol->value
                        : text_start + entry_offset);                         : text_start + text_header_size);
   
 #ifdef COFF_ENCAPSULATE  #ifdef COFF_ENCAPSULATE
   if (need_coff_header)    if (need_coff_header)
     {      {
Line 3383  write_header () Line 3994  write_header ()
       coffheader.data_start = dp->s_vaddr;        coffheader.data_start = dp->s_vaddr;
     }      }
 #endif  #endif
   
 #ifdef INITIALIZE_HEADER    if (strip_symbols == STRIP_ALL)
   INITIALIZE_HEADER;      nsyms = 0;
     else
       {
         nsyms = (defined_global_sym_count
                  + undefined_global_sym_count);
         if (discard_locals == DISCARD_L)
           nsyms += non_L_local_sym_count;
         else if (discard_locals == DISCARD_NONE)
           nsyms += local_sym_count;
         /* One extra for following reference on indirects */
         if (output_style == OUTPUT_RELOCATABLE)
   #ifndef NeXT
           nsyms += set_symbol_count + global_indirect_count;
   #else
           nsyms += set_symbol_count;
   #endif
       }
   
     if (strip_symbols == STRIP_NONE)
       nsyms += debugger_sym_count;
   
     outheader.a_syms = nsyms * sizeof (struct nlist);
   
     if (output_style == OUTPUT_RELOCATABLE)
       {
         outheader.a_trsize = text_reloc_size;
         outheader.a_drsize = data_reloc_size;
       }
     else
       {
         outheader.a_trsize = 0;
         outheader.a_drsize = 0;
   #ifdef tek4300
         /* UTek has been known to panic without the following ... */
         outheader.a_textoff = ZMOFF;
         outheader.a_dataoff = ZMOFF + text_size;
         outheader.a_textaddr = text_start;
         outheader.a_dataaddr = data_start;
         outheader.a_bssaddr = data_start + data_size;
   #endif
       }
   
     /* Initialize the various file offsets.  */
   
     output_text_offset = N_TXTOFF (outheader);
   #ifdef N_DATOFF
     output_data_offset = N_DATOFF (outheader);
   #else
     output_data_offset = output_text_offset + text_size;
   #endif
   #ifdef N_TRELOFF
     output_trel_offset = N_TRELOFF (outheader);
   #else
     output_trel_offset = output_data_offset + data_size;
   #endif
   #ifdef N_DRELOFF
     output_drel_offset = N_DRELOFF (outheader);
   #else
     output_drel_offset = output_trel_offset + text_reloc_size;
   #endif
     output_syms_offset = N_SYMOFF (outheader);
     output_strs_offset = N_STROFF (outheader);
   }
   
   /* Compute more section offsets once the size of the string table is known.  */
   
   void
   compute_more_a_out_section_offsets ()
   {
     output_symseg_offset = output_strs_offset + output_strs_size;
   }
   
   /* Write the a.out header once everything else is known.  */
   
   void
   write_a_out_header ()
   {
     lseek (outdesc, 0L, 0);
   
   #ifdef COFF_ENCAPSULATE
     if (need_coff_header)
       mywrite (&coffheader, sizeof coffheader, 1, outdesc);
   #endif
   
   #ifdef tek4300
     if (outheader.a_magic == ZMAGIC)
       mywrite (&outheader, sizeof outheader, 1, outdesc);
     else
   #endif
     mywrite (&outheader, sizeof (struct exec), 1, outdesc);
   
     /* Output whatever padding is required in the executable file
        between the header and the start of the text.  */
   
   #ifndef COFF_ENCAPSULATE
     padfile (N_TXTOFF (outheader) - sizeof outheader, outdesc);
   #endif
   }
   
   #endif
   
   #ifdef MACH_O
   
   /* Stuff pertaining to creating Mach-O files. */
   
   /* Convert the Mach-O style n_sect references into something the rest
      of the loader can understand.  */
   
   void
   translate_mach_o_symbols (entry)
        struct file_entry *entry;
   {
     int i, n, g;
     struct nlist *sym;
   
     n = entry->syms_size / sizeof (struct nlist);
     for (i = 0; i < n; ++i)
       if (((sym = &entry->symbols[i])->n_type & ~N_EXT) == N_SECT)
         {
           if (sym->n_sect == entry->text_ordinal)
             sym->n_type = (sym->n_type & N_EXT) | N_TEXT;
           else if (sym->n_sect == entry->data_ordinal)
             sym->n_type = (sym->n_type & N_EXT) | N_DATA;
           else if (sym->n_sect == entry->bss_ordinal)
             sym->n_type = (sym->n_type & N_EXT) | N_BSS;
           else
             fatal_with_file ("unknown section referenced in symbols of ", entry);
           sym->n_sect = 0;
         }
       else if ((sym = &entry->symbols[i])->n_type == N_SLINE)
         {
           if (sym->n_sect == entry->text_ordinal)
             sym->n_type = N_SLINE;
           else if (sym->n_sect == entry->data_ordinal)
             sym->n_type = N_DSLINE;
           else if (sym->n_sect == entry->bss_ordinal)
             sym->n_type = N_BSLINE;
           else
             fatal_with_file ("unknown section referenced in debugging symbols of ", entry);
         }
   }
   
   /* Convert Mach-O style relocation info into a.out style relocation
      info internally.  */
   void
   translate_mach_o_relocation (entry, reloc, count)
        struct file_entry *entry;
        struct relocation_info *reloc;
        int count;
   {
     int i;
   
     for (i = 0; i < count; ++i)
       if (!RELOC_EXTERN_P(&reloc[i]))
         if (RELOC_TYPE(&reloc[i]) == R_ABS)
           RELOC_TYPE(&reloc[i]) = N_ABS;
         else if (RELOC_TYPE(&reloc[i]) == entry->text_ordinal)
           RELOC_TYPE(&reloc[i]) = N_TEXT;
         else if (RELOC_TYPE(&reloc[i]) == entry->data_ordinal)
           RELOC_TYPE(&reloc[i]) = N_DATA;
         else if (RELOC_TYPE(&reloc[i]) == entry->bss_ordinal)
           RELOC_TYPE(&reloc[i]) = N_BSS;
         else
           fatal_with_file ("unknown section ordinal in relocation info of ", entry);
   }
   
   /* Header structure for OUTPUT_RELOCATABLE.  */
   
   struct
   {
     struct mach_header header;
     struct segment_command segment;
     struct section text;
     struct section data;
     struct section bss;
     struct symtab_command symtab;
   #ifdef LC_SYMSEG
     struct symseg_command symseg;
   #endif
   } m_object;
   
   #ifdef NeXT
   #define CPU_TYPE CPU_TYPE_MC68030
   #define CPU_SUBTYPE CPU_SUBTYPE_NeXT
   #define THREAD_FLAVOR NeXT_THREAD_STATE_REGS
   #define THREAD_COUNT NeXT_THREAD_STATE_REGS_COUNT
   typedef struct NeXT_thread_state_regs thread_state;
   #define thread_state_entry_field pc
   #endif
   
   /* Header structure for all executable output forms.  */
   
   struct
   {
     struct mach_header header;
     struct segment_command pagezero;
     struct segment_command text_segment;
     struct section text;
     struct segment_command data_segment;
     struct section data;
     struct section bss;
     struct thread_command unixthread;
     unsigned long int flavor;
     unsigned long int count;
     thread_state state;
     struct symtab_command symtab;
   #ifdef LC_SYMSEG
     struct symseg_command symseg;
   #endif
   } m_exec;
   
   /* Compute text_start and text_header_size for an a.out file.  */
   
   void
   initialize_mach_o_text_start ()
   {
     if (output_style != OUTPUT_RELOCATABLE)
       {
         text_header_size = sizeof m_exec;
         if (!T_flag_specified && output_style != OUTPUT_RELOCATABLE)
           /* We reserve the first page of an executable to trap NULL dereferences.  */
           text_start = page_size;
       }
   }
   
   /* Compute data_start once text_size is known.  */
   
   void
   initialize_mach_o_data_start ()
   {
     if (! Tdata_flag_specified)
       data_start = text_start + text_size;
   }
   
   /* Compute offsets of various pieces of the Mach-O output file.  */
   void
   compute_mach_o_section_offsets ()
   {
     int header_size, trsize, drsize;
   
     switch (output_style)
       {
       case OUTPUT_RELOCATABLE:
         header_size = sizeof m_object;
         break;
       default:
         header_size = sizeof m_exec;
         break;
       }
   
     if (strip_symbols == STRIP_ALL)
       nsyms = 0;
     else
       {
         nsyms = (defined_global_sym_count
                  + undefined_global_sym_count);
         if (discard_locals == DISCARD_L)
           nsyms += non_L_local_sym_count;
         else if (discard_locals == DISCARD_NONE)
           nsyms += local_sym_count;
         /* One extra for following reference on indirects */
         if (output_style == OUTPUT_RELOCATABLE)
   #ifndef NeXT
           nsyms += set_symbol_count + global_indirect_count;
   #else
           nsyms += set_symbol_count;
   #endif
       }
   
     if (strip_symbols == STRIP_NONE)
       nsyms += debugger_sym_count;
   
     output_text_offset = header_size;
     output_data_offset = output_text_offset + text_size;
     output_trel_offset = output_data_offset + data_size;
     if (output_style == OUTPUT_RELOCATABLE)
       trsize = text_reloc_size, drsize = data_reloc_size;
     else
       trsize = drsize = 0;
     output_drel_offset = output_trel_offset + trsize;
     output_syms_offset = output_drel_offset + drsize;
     output_strs_offset = output_syms_offset + nsyms * sizeof (struct nlist);
   }
   
   /* Compute more section offsets once the size of the string table is known.  */
   void
   compute_more_mach_o_section_offsets ()
   {
     output_symseg_offset = output_strs_offset + output_strs_size;
   }
   
   /* Write the Mach-O header once everything else is known.  */
   
   void
   write_mach_o_header ()
   {
     struct mach_header header;
     struct section text, data, bss;
     struct symtab_command symtab;
   #ifdef LC_SYMSEG
     struct symseg_command symseg;
   #endif
     thread_state state;
   
     lseek (outdesc, 0L, 0);
   
   
     header.magic = MH_MAGIC;
     header.cputype = CPU_TYPE;
     header.cpusubtype = CPU_SUBTYPE;
     header.filetype = output_style == OUTPUT_RELOCATABLE ? MH_OBJECT : MH_EXECUTE;
   #ifdef LC_SYMSEG
     switch (output_style)
       {
       case OUTPUT_RELOCATABLE:
         header.ncmds = 3;
         header.sizeofcmds = sizeof m_object - sizeof header;
         break;
       default:
         header.ncmds = 6;
         header.sizeofcmds = sizeof m_exec - sizeof header;
         break;
       }
   #else
     switch (output_style)
       {
       case OUTPUT_RELOCATABLE:
         header.ncmds = 2;
         header.sizeofcmds = sizeof m_object - sizeof header;
         break;
       default:
         header.ncmds = 5;
         header.sizeofcmds = sizeof m_exec - sizeof header;
         break;
       }
   #endif
     header.flags = undefined_global_sym_count ? 0 : MH_NOUNDEFS;
   
     bzero((char *) &text, sizeof text);
     strncpy(text.sectname, SECT_TEXT, sizeof text.sectname);
     strncpy(text.segname, SEG_TEXT, sizeof text.segname);
     text.addr = text_start;
     text.size = text_size;
     text.offset = output_text_offset;
     text.align = text.addr % sizeof (double) ? sizeof (int) : sizeof (double);
     text.reloff = output_trel_offset;
     text.nreloc = output_style == OUTPUT_RELOCATABLE
       ? text_reloc_size / sizeof (struct relocation_info) : 0;
     text.flags = 0;
   
     bzero((char *) &data, sizeof data);
     strncpy(data.sectname, SECT_DATA, sizeof data.sectname);
     strncpy(data.segname, output_style == OUTPUT_WRITABLE_TEXT ? SEG_TEXT : SEG_DATA,
             sizeof data.segname);
     data.addr = data_start;
     data.size = data_size;
     data.offset = output_data_offset;
     data.align = data.addr % sizeof (double) ? sizeof (int) : sizeof (double);
     data.reloff = output_drel_offset;
     data.nreloc = output_style == OUTPUT_RELOCATABLE
       ? data_reloc_size / sizeof (struct relocation_info) : 0;
     data.flags = 0;
   
     bzero((char *) &bss, sizeof bss);
     strncpy(bss.sectname, SECT_BSS, sizeof data.sectname);
     strncpy(bss.segname, output_style == OUTPUT_WRITABLE_TEXT ? SEG_TEXT : SEG_DATA,
             sizeof bss.segname);
     bss.addr = data_start + data_size;
     bss.size = bss_size;
     bss.align = bss.addr % sizeof (double) ? sizeof (int) : sizeof (double);
     bss.reloff = 0;
     bss.nreloc = 0;
     bss.flags = S_ZEROFILL;
   
     symtab.cmd = LC_SYMTAB;
     symtab.cmdsize = sizeof symtab;
     symtab.symoff = output_syms_offset;
     symtab.nsyms = output_syms_size / sizeof (struct nlist);
     symtab.stroff = output_strs_offset;
     symtab.strsize = output_strs_size;
   
   #ifdef LC_SYMSEG
     symseg.cmd = LC_SYMSEG;
     symseg.cmdsize = sizeof symseg;
     symseg.offset = output_symseg_offset;
     symseg.size = output_symseg_size;
   #endif
   
     switch (output_style)
       {
       case OUTPUT_RELOCATABLE:
         m_object.header = header;
         m_object.segment.cmd = LC_SEGMENT;
         m_object.segment.cmdsize = sizeof (struct segment_command) + 3 * sizeof (struct section);
         strncpy(m_object.segment.segname, SEG_TEXT, sizeof m_object.segment.segname);
         m_object.segment.vmaddr = 0;
         m_object.segment.vmsize = text.size + data.size + bss.size;
         m_object.segment.fileoff = text.offset;
         m_object.segment.filesize = text.size + data.size;
         m_object.segment.maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
         m_object.segment.initprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
         m_object.segment.nsects = 3;
         m_object.segment.flags = 0;
         m_object.text = text;
         m_object.data = data;
         m_object.bss = bss;
         m_object.symtab = symtab;
   #ifdef LC_SYMSEG
         m_object.symseg = symseg;
   #endif
         mywrite((char *) &m_object, 1, sizeof m_object, outdesc);
         break;
   
       default:
         m_exec.header = header;
         m_exec.pagezero.cmd = LC_SEGMENT;
         m_exec.pagezero.cmdsize = sizeof (struct segment_command);
         strncpy(m_exec.pagezero.segname, SEG_PAGEZERO, sizeof m_exec.pagezero.segname);
         m_exec.pagezero.vmaddr = 0;
         m_exec.pagezero.vmsize = page_size;
         m_exec.pagezero.fileoff = 0;
         m_exec.pagezero.filesize = 0;
         m_exec.pagezero.maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
         m_exec.pagezero.initprot = 0;
         m_exec.pagezero.nsects = 0;
         m_exec.pagezero.flags = 0;
         m_exec.text_segment.cmd = LC_SEGMENT;
         m_exec.text_segment.cmdsize = sizeof (struct segment_command) + sizeof (struct section);
         strncpy(m_exec.text_segment.segname, SEG_TEXT, sizeof m_exec.text_segment.segname);
         m_exec.text_segment.vmaddr = text_start;
         m_exec.text_segment.vmsize = text_size;
         m_exec.text_segment.fileoff = output_text_offset;
         m_exec.text_segment.filesize = text_size;
         m_exec.text_segment.maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
         m_exec.text_segment.initprot = VM_PROT_READ | VM_PROT_EXECUTE;
         if (output_style == OUTPUT_WRITABLE_TEXT)
           m_exec.text_segment.initprot |= VM_PROT_WRITE;
         m_exec.text_segment.nsects = 1;
         m_exec.text_segment.flags = 0;
         m_exec.text = text;
         m_exec.data_segment.cmd = LC_SEGMENT;
         m_exec.data_segment.cmdsize = sizeof (struct segment_command) + 2 * sizeof (struct section);
         strncpy(m_exec.data_segment.segname, SEG_DATA, sizeof m_exec.data_segment.segname);
         m_exec.data_segment.vmaddr = data_start;
         m_exec.data_segment.vmsize = data_size + bss_size;
         m_exec.data_segment.fileoff = output_data_offset;
         m_exec.data_segment.filesize = data_size;
         m_exec.data_segment.maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
         m_exec.data_segment.initprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
         m_exec.data_segment.nsects = 2;
         m_exec.data_segment.flags = 0;
         m_exec.data = data;
         m_exec.bss = bss;
         m_exec.unixthread.cmd = LC_UNIXTHREAD;
         m_exec.unixthread.cmdsize
           = sizeof (struct thread_command) + 2 * sizeof (long int) + sizeof (thread_state);
         m_exec.flavor = THREAD_FLAVOR;
         m_exec.count = THREAD_COUNT;
         m_exec.state.thread_state_entry_field = entry_symbol
           ? entry_symbol->value : text_start + text_header_size;
         m_exec.symtab = symtab;
   #ifdef LC_SYMSEG
         m_exec.symseg = symseg;
   #endif
         mywrite((char *) &m_exec, 1, sizeof m_exec, outdesc);
         break;
       }
   }
   
   /* Translate a.out style symbols into Mach-O style symbols.  */
   
   void
   generate_mach_o_symbols (syms, nsyms)
        struct nlist *syms;
        int nsyms;
   {
     int i;
   
     for (i = 0; i < nsyms; ++i)
       switch (syms[i].n_type)
         {
         case N_TEXT:
         case N_TEXT | N_EXT:
           syms[i].n_type = syms[i].n_type & N_EXT | N_SECT;
           syms[i].n_sect = 1;     /* text section ordinal */
           break;
         case N_DATA:
         case N_DATA | N_EXT:
           syms[i].n_type = syms[i].n_type & N_EXT | N_SECT;
           syms[i].n_sect = 2;     /* data section ordinal */
           break;
         case N_BSS:
         case N_BSS | N_EXT:
           syms[i].n_type = syms[i].n_type & N_EXT | N_BSS;
           syms[i].n_sect = 3;     /* bss section ordinal */
           break;
         case N_SLINE:
           syms[i].n_type = N_SLINE;
           syms[i].n_sect = 1;     /* text section ordinal */
           break;
         case N_DSLINE:
           syms[i].n_type = N_SLINE;
           syms[i].n_sect = 2;     /* data section ordinal */
           break;
         case N_BSLINE:
           syms[i].n_type = N_SLINE;
           syms[i].n_sect = 3;     /* bss section ordinal */
           break;
         }
   }
   
   /* Translate a.out style relocation info into Mach-O style relocation
      info.  */
   
   void
   generate_mach_o_relocations (reloc, nreloc)
        struct relocation_info *reloc;
        int nreloc;
   {
     int i;
   
     for (i = 0; i < nreloc; ++i)
       if (!RELOC_EXTERN_P (&reloc[i]))
         switch (RELOC_TYPE (&reloc[i]))
           {
           case N_ABS:
           case N_ABS | N_EXT:
             RELOC_TYPE (&reloc[i]) = R_ABS;
             break;
           case N_TEXT:
           case N_TEXT | N_EXT:
             RELOC_TYPE (&reloc[i]) = 1; /* output text section ordinal */
             break;
           case N_DATA:
           case N_DATA | N_EXT:
             RELOC_TYPE (&reloc[i]) = 2; /* output data section ordinal */
             break;
           case N_BSS:
           case N_BSS | N_EXT:
             RELOC_TYPE (&reloc[i]) = 3; /* output bss section ordinal */
             break;
           }
   }
   
   #endif
   
   /* The following functions are simple switches according to the
      output style.  */
   
   /* Compute text_start and text_header_size as appropriate for the
      output format.  */
   
   void
   initialize_text_start ()
   {
   #ifdef A_OUT
     if (output_file_type == IS_A_OUT)
       {
         initialize_a_out_text_start ();
         return;
       }
   #endif
   #ifdef MACH_O
     if (output_file_type == IS_MACH_O)
       {
         initialize_mach_o_text_start ();
         return;
       }
   #endif
     fatal ("unknown output file type (enum file_type)", (char *) 0);
   }
   
   /* Initialize data_start as appropriate to the output format, once text_size
      is known.  */
   
   void
   initialize_data_start ()
   {
   #ifdef A_OUT
     if (output_file_type == IS_A_OUT)
       {
         initialize_a_out_data_start ();
         return;
       }
   #endif
   #ifdef MACH_O
     if (output_file_type == IS_MACH_O)
       {
         initialize_mach_o_data_start ();
         return;
       }
   #endif
     fatal ("unknown output file type (enum file_type)", (char *) 0);
   }
   
   /* Compute offsets of the various sections within the output file.  */
   
   void
   compute_section_offsets ()
   {
   #ifdef A_OUT
     if (output_file_type == IS_A_OUT)
       {
         compute_a_out_section_offsets ();
         return;
       }
   #endif
   #ifdef MACH_O
     if (output_file_type == IS_MACH_O)
       {
         compute_mach_o_section_offsets ();
         return;
       }
 #endif  #endif
     fatal ("unknown output file type (enum file_type)", (char *) 0);
   }
   
   if (strip_symbols == STRIP_ALL)  /* Compute more section offsets, once the size of the string table
     nsyms = 0;     is finalized.  */
   else  void
   compute_more_section_offsets ()
   {
   #ifdef A_OUT
     if (output_file_type == IS_A_OUT)
     {      {
       nsyms = (defined_global_sym_count        compute_more_a_out_section_offsets ();
                + undefined_global_sym_count);        return;
       if (discard_locals == DISCARD_L)  
         nsyms += non_L_local_sym_count;  
       else if (discard_locals == DISCARD_NONE)  
         nsyms += local_sym_count;  
       /* One extra for following reference on indirects */  
       if (relocatable_output)  
         nsyms += set_symbol_count + global_indirect_count;  
     }      }
   #endif
   #ifdef MACH_O
     if (output_file_type == IS_MACH_O)
       {
         compute_more_mach_o_section_offsets ();
         return;
       }
   #endif
     fatal ("unknown output file type (enum file_type)", (char *) 0);
   }
   
   if (strip_symbols == STRIP_NONE)  /* Write the output file header, once everything is known.  */
     nsyms += debugger_sym_count;  void
   write_header ()
   outheader.a_syms = nsyms * sizeof (struct nlist);  {
   #ifdef A_OUT
   if (relocatable_output)    if (output_file_type == IS_A_OUT)
     {      {
       outheader.a_trsize = text_reloc_size;        write_a_out_header ();
       outheader.a_drsize = data_reloc_size;        return;
     }      }
   else  #endif
   #ifdef MACH_O
     if (output_file_type == IS_MACH_O)
     {      {
       outheader.a_trsize = 0;        write_mach_o_header ();
       outheader.a_drsize = 0;        return;
     }      }
   
 #ifdef COFF_ENCAPSULATE  
   if (need_coff_header)  
     mywrite (&coffheader, sizeof coffheader, 1, outdesc);  
 #endif  #endif
   mywrite (&outheader, sizeof (struct exec), 1, outdesc);    fatal ("unknown output file type (enum file_type)", (char *) 0);
   }
   
   /* Write the output file */
   
   /* Output whatever padding is required in the executable file  void
      between the header and the start of the text.  */  write_output ()
   {
     struct stat statbuf;
     int filemode, mask;
   
 #ifndef COFF_ENCAPSULATE    /* Remove the old file in case it is owned by someone else.
   padfile (N_TXTOFF (outheader) - sizeof outheader, outdesc);       This prevents spurious "not owner" error messages.
 #endif       Don't check for errors from unlink; we don't really care
        whether it worked.
   
        Note that this means that if the output file is hard linked,
        the other names will still have the old contents.  This is
        the way Unix ld works; I'm going to consider it a feature.  */
     (void) unlink (output_filename);
     
     outdesc = open (output_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
     if (outdesc < 0) perror_name (output_filename);
   
     if (fstat (outdesc, &statbuf) < 0)
       perror_name (output_filename);
   
     filemode = statbuf.st_mode;
   
     chmod (output_filename, filemode & ~0111);
   
     /* Calculate the offsets of the various pieces of the output file.  */
     compute_section_offsets ();
   
     /* Output the text and data segments, relocating as we go.  */
     write_text ();
     write_data ();
   
     /* Output the merged relocation info, if requested with `-r'.  */
     if (output_style == OUTPUT_RELOCATABLE)
       write_rel ();
   
     /* Output the symbol table (both globals and locals).  */
     write_syms ();
   
     /* At this point the total size of the symbol table and string table
        are finalized.  */
     compute_more_section_offsets ();
   
     /* Copy any GDB symbol segments from input files.  */
     write_symsegs ();
   
     /* Now that everything is known about the output file, write its header.  */
     write_header ();
   
     close (outdesc);
   
     mask = umask (0);
     umask (mask);
   
     if (chmod (output_filename, filemode | (0111 & ~mask)) == -1)
       perror_name (output_filename);
 }  }
   
   void modify_location (), perform_relocation (), copy_text (), copy_data ();
   
 /* Relocate the text segment of each input file  /* Relocate the text segment of each input file
    and write to the output file.  */     and write to the output file.  */
   
Line 3442  write_text () Line 4728  write_text ()
   if (trace_files)    if (trace_files)
     fprintf (stderr, "Copying and relocating text:\n\n");      fprintf (stderr, "Copying and relocating text:\n\n");
   
   each_full_file (copy_text);    lseek (outdesc, output_text_offset + text_header_size, 0);
   
     each_full_file (copy_text, 0);
   file_close ();    file_close ();
   
   if (trace_files)    if (trace_files)
Line 3451  write_text () Line 4739  write_text ()
   padfile (text_pad, outdesc);    padfile (text_pad, outdesc);
 }  }
   
 int  
 text_offset (entry)  
      struct file_entry *entry;  
 {  
   return entry->starting_offset + N_TXTOFF (entry->header);  
 }  
   
 /* Read in all of the relocation information */  /* Read in all of the relocation information */
   
 void  void
 read_relocation ()  read_relocation ()
 {  {
   each_full_file (read_file_relocation);    each_full_file (read_file_relocation, 0);
 }  }
   
 /* Read in the relocation sections of ENTRY if necessary */  /* Read in the relocation sections of ENTRY if necessary */
Line 3479  read_file_relocation (entry) Line 4760  read_file_relocation (entry)
   desc = -1;    desc = -1;
   if (!entry->textrel)    if (!entry->textrel)
     {      {
       reloc = (struct relocation_info *) xmalloc (entry->header.a_trsize);        reloc = (struct relocation_info *) xmalloc (entry->text_reloc_size);
       desc = file_open (entry);        desc = file_open (entry);
       lseek (desc,        lseek (desc, entry->starting_offset + entry->text_reloc_offset, L_SET);
              text_offset (entry) + entry->header.a_text + entry->header.a_data,        if (entry->text_reloc_size != (read_return = read (desc, reloc, entry->text_reloc_size)))
              L_SET);  
       if (entry->header.a_trsize != (read_return = read (desc, reloc, entry->header.a_trsize)))  
         {          {
           fprintf (stderr, "Return from read: %d\n", read_return);            fprintf (stderr, "Return from read: %d\n", read_return);
           fatal_with_file ("premature eof in text relocation of ", entry);            fatal_with_file ("premature eof in text relocation of ", entry);
Line 3494  read_file_relocation (entry) Line 4773  read_file_relocation (entry)
   
   if (!entry->datarel)    if (!entry->datarel)
     {      {
       reloc = (struct relocation_info *) xmalloc (entry->header.a_drsize);        reloc = (struct relocation_info *) xmalloc (entry->data_reloc_size);
       if (desc == -1) desc = file_open (entry);        if (desc == -1) desc = file_open (entry);
       lseek (desc,        lseek (desc, entry->starting_offset + entry->data_reloc_offset, L_SET);
              text_offset (entry) + entry->header.a_text        if (entry->data_reloc_size != read (desc, reloc, entry->data_reloc_size))
              + entry->header.a_data + entry->header.a_trsize,  
              L_SET);  
       if (entry->header.a_drsize != read (desc, reloc, entry->header.a_drsize))  
         fatal_with_file ("premature eof in data relocation of ", entry);          fatal_with_file ("premature eof in data relocation of ", entry);
       entry->datarel = reloc;        entry->datarel = reloc;
     }      }
   
   #ifdef MACH_O
     if (entry->file_type == IS_MACH_O)
       {
         translate_mach_o_relocation (entry, entry->textrel,
                                      entry->text_reloc_size / sizeof (struct relocation_info));
         translate_mach_o_relocation (entry, entry->datarel,
                                      entry->data_reloc_size / sizeof (struct relocation_info));
       }
   #endif
 }  }
   
 /* Read the text segment contents of ENTRY, relocate them,  /* Read the text segment contents of ENTRY, relocate them,
Line 3525  copy_text (entry) Line 4811  copy_text (entry)
   
   /* Allocate space for the file's text section */    /* Allocate space for the file's text section */
   
   bytes = (char *) alloca (entry->header.a_text);    bytes = (char *) alloca (entry->text_size);
   
   /* Deal with relocation information however is appropriate */    /* Deal with relocation information however is appropriate */
   
   if (entry->textrel)  reloc = entry->textrel;    if (entry->textrel)  reloc = entry->textrel;
   else if (relocatable_output)    else if (output_style == OUTPUT_RELOCATABLE)
     {      {
       read_file_relocation (entry);        read_file_relocation (entry);
       reloc = entry->textrel;        reloc = entry->textrel;
     }      }
   else    else
     {      {
       reloc = (struct relocation_info *) alloca (entry->header.a_trsize);        reloc = (struct relocation_info *) alloca (entry->text_reloc_size);
       lseek (desc, text_offset (entry) + entry->header.a_text + entry->header.a_data, 0);        lseek (desc, entry->starting_offset + entry->text_reloc_offset, L_SET);
       if (entry->header.a_trsize != read (desc, reloc, entry->header.a_trsize))        if (entry->text_reloc_size != read (desc, reloc, entry->text_reloc_size))
         fatal_with_file ("premature eof in text relocation of ", entry);          fatal_with_file ("premature eof in text relocation of ", entry);
   #ifdef MACH_O
         if (entry->file_type == IS_MACH_O)
           translate_mach_o_relocation (entry, reloc,
                                        entry->text_reloc_size / sizeof (struct relocation_info));
   #endif
     }      }
   
   /* Read the text section into core.  */    /* Read the text section into core.  */
   
   lseek (desc, text_offset (entry), 0);    lseek (desc, entry->starting_offset + entry->text_offset, L_SET);
   if (entry->header.a_text != read (desc, bytes, entry->header.a_text))    if (entry->text_size != read (desc, bytes, entry->text_size))
     fatal_with_file ("premature eof in text section of ", entry);      fatal_with_file ("premature eof in text section of ", entry);
   
   
   /* Relocate the text according to the text relocation.  */    /* Relocate the text according to the text relocation.  */
   
   perform_relocation (bytes, entry->text_start_address, entry->header.a_text,    perform_relocation (bytes, entry->text_start_address - entry->orig_text_address,
                       reloc, entry->header.a_trsize, entry);                        entry->text_size, reloc, entry->text_reloc_size, entry);
   
   /* Write the relocated text to the output file.  */    /* Write the relocated text to the output file.  */
   
   mywrite (bytes, 1, entry->header.a_text, outdesc);    mywrite (bytes, 1, entry->text_size, outdesc);
 }  }
   
 /* Relocate the data segment of each input file  /* Relocate the data segment of each input file
Line 3569  write_data () Line 4859  write_data ()
   if (trace_files)    if (trace_files)
     fprintf (stderr, "Copying and relocating data:\n\n");      fprintf (stderr, "Copying and relocating data:\n\n");
   
   each_full_file (copy_data);    lseek (outdesc, output_data_offset, 0);
   
     each_full_file (copy_data, 0);
   file_close ();    file_close ();
   
   /* Write out the set element vectors.  See digest symbols for    /* Write out the set element vectors.  See digest symbols for
Line 3603  copy_data (entry) Line 4895  copy_data (entry)
   
   desc = file_open (entry);    desc = file_open (entry);
   
   bytes = (char *) alloca (entry->header.a_data);    bytes = (char *) alloca (entry->data_size);
   
   if (entry->datarel) reloc = entry->datarel;    if (entry->datarel) reloc = entry->datarel;
   else if (relocatable_output)  /* Will need this again */    else if (output_style == OUTPUT_RELOCATABLE)  /* Will need this again */
     {      {
       read_file_relocation (entry);        read_file_relocation (entry);
       reloc = entry->datarel;        reloc = entry->datarel;
     }      }
   else    else
     {      {
       reloc = (struct relocation_info *) alloca (entry->header.a_drsize);        reloc = (struct relocation_info *) alloca (entry->data_reloc_size);
       lseek (desc, text_offset (entry) + entry->header.a_text        lseek (desc, entry->starting_offset + entry->data_reloc_offset, L_SET);
              + entry->header.a_data + entry->header.a_trsize,        if (entry->data_reloc_size != read (desc, reloc, entry->data_reloc_size))
              0);  
       if (entry->header.a_drsize != read (desc, reloc, entry->header.a_drsize))  
         fatal_with_file ("premature eof in data relocation of ", entry);          fatal_with_file ("premature eof in data relocation of ", entry);
   #ifdef MACH_O
         if (entry->file_type == IS_MACH_O)
           translate_mach_o_relocation (entry, reloc,
                                        entry->data_reloc_size / sizeof (struct relocation_info));
   #endif
     }      }
   
   lseek (desc, text_offset (entry) + entry->header.a_text, 0);    lseek (desc, entry->starting_offset + entry->data_offset, L_SET);
   if (entry->header.a_data != read (desc, bytes, entry->header.a_data))    if (entry->data_size != read (desc, bytes, entry->data_size))
     fatal_with_file ("premature eof in data section of ", entry);      fatal_with_file ("premature eof in data section of ", entry);
   
   perform_relocation (bytes, entry->data_start_address - entry->header.a_text,    perform_relocation (bytes, entry->data_start_address - entry->orig_data_address,
                       entry->header.a_data, reloc, entry->header.a_drsize, entry);                        entry->data_size, reloc, entry->data_reloc_size, entry);
   
   mywrite (bytes, 1, entry->header.a_data, outdesc);    mywrite (bytes, 1, entry->data_size, outdesc);
 }  }
   
 /* Relocate ENTRY's text or data section contents.  /* Relocate ENTRY's text or data section contents.
Line 3638  copy_data (entry) Line 4933  copy_data (entry)
      in the output file and its address in the input file.       in the output file and its address in the input file.
    RELOC_INFO is the address of the relocation info, in core.     RELOC_INFO is the address of the relocation info, in core.
    RELOC_SIZE is its length in bytes.  */     RELOC_SIZE is its length in bytes.  */
 /* This version is about to be severley hacked by Randy.  Hope it  /* This version is about to be severly hacked by Randy.  Hope it
    works afterwards. */     works afterwards. */
 void  void
 perform_relocation (data, pc_relocation, data_size, reloc_info, reloc_size, entry)  perform_relocation (data, pc_relocation, data_size, reloc_info, reloc_size, entry)
Line 3652  perform_relocation (data, pc_relocation, Line 4947  perform_relocation (data, pc_relocation,
   register struct relocation_info *p = reloc_info;    register struct relocation_info *p = reloc_info;
   struct relocation_info *end    struct relocation_info *end
     = reloc_info + reloc_size / sizeof (struct relocation_info);      = reloc_info + reloc_size / sizeof (struct relocation_info);
   int text_relocation = entry->text_start_address;    int text_relocation = entry->text_start_address - entry->orig_text_address;
   int data_relocation = entry->data_start_address - entry->header.a_text;    int data_relocation = entry->data_start_address - entry->orig_data_address;
   int bss_relocation    int bss_relocation = entry->bss_start_address - entry->orig_bss_address;
     = entry->bss_start_address - entry->header.a_text - entry->header.a_data;  
   
   for (; p < end; p++)    for (; p < end; p++)
     {      {
Line 3680  perform_relocation (data, pc_relocation, Line 4974  perform_relocation (data, pc_relocation,
             sp = (symbol *) sp->value;              sp = (symbol *) sp->value;
 #endif  #endif
   
           if (symindex >= entry->header.a_syms)            if (symindex >= entry->syms_size)
             fatal_with_file ("relocation symbolnum out of range in ", entry);              fatal_with_file ("relocation symbolnum out of range in ", entry);
   
           /* If the symbol is undefined, leave it at zero.  */            /* If the symbol is undefined, leave it at zero.  */
Line 3698  perform_relocation (data, pc_relocation, Line 4992  perform_relocation (data, pc_relocation,
   
         case N_DATA:          case N_DATA:
         case N_DATA | N_EXT:          case N_DATA | N_EXT:
           /* A word that points to beginning of the the data section  
              initially contains not 0 but rather the "address" of that section  
              in the input file, which is the length of the file's text.  */  
           relocation = data_relocation;            relocation = data_relocation;
           break;            break;
   
         case N_BSS:          case N_BSS:
         case N_BSS | N_EXT:          case N_BSS | N_EXT:
           /* Similarly, an input word pointing to the beginning of the bss  
              initially contains the length of text plus data of the file.  */  
           relocation = bss_relocation;            relocation = bss_relocation;
           break;            break;
   
Line 3725  perform_relocation (data, pc_relocation, Line 5014  perform_relocation (data, pc_relocation,
   
 #ifdef RELOC_ADD_EXTRA  #ifdef RELOC_ADD_EXTRA
       relocation += RELOC_ADD_EXTRA(p);        relocation += RELOC_ADD_EXTRA(p);
       if (relocatable_output)        if (output_style == OUTPUT_RELOCATABLE)
         {          {
           /* If this RELOC_ADD_EXTRA is 0, it means that the            /* If this RELOC_ADD_EXTRA is 0, it means that the
              symbol was external and the relocation does not               symbol was external and the relocation does not
Line 3756  perform_relocation (data, pc_relocation, Line 5045  perform_relocation (data, pc_relocation,
       /* Unshifted mask for relocation */        /* Unshifted mask for relocation */
       mask = 1 << RELOC_TARGET_BITSIZE(p) - 1;        mask = 1 << RELOC_TARGET_BITSIZE(p) - 1;
       mask |= mask - 1;        mask |= mask - 1;
       relocation &= mask;  
   
       /* Shift everything up to where it's going to be used */        /* Shift everything up to where it's going to be used */
       relocation <<= RELOC_TARGET_BITPOS(p);        relocation <<= RELOC_TARGET_BITPOS(p);
       mask <<= RELOC_TARGET_BITPOS(p);        mask <<= RELOC_TARGET_BITPOS(p);
   
   #ifdef ns32000
         /* This code by Ian Dall for the ns32k displacements */
         {
           char * loc = (data + addr);
           int bytes = (1 << RELOC_TARGET_SIZE(p));
           void put_num(), put_disp(), put_imm();
           int get_num(), get_disp(), get_imm();
           switch(p->r_disp)
             {
             case 0:
               if (RELOC_MEMORY_SUB_P(p))
                 put_imm(loc, relocation - get_imm(loc, bytes), bytes);
               else if (RELOC_MEMORY_ADD_P(p))
                 put_imm(loc, relocation + get_imm(loc, bytes), bytes);
               break;
             case 1:
               if (RELOC_MEMORY_SUB_P(p))
                 put_disp(loc, relocation - get_disp(loc, bytes), bytes);
               else if (RELOC_MEMORY_ADD_P(p))
                 put_disp(loc, relocation + get_disp(loc, bytes), bytes);
               break;
             case 2:
               if (RELOC_MEMORY_SUB_P(p))
                 put_num(loc, relocation - get_num(loc, bytes), bytes);
               else if (RELOC_MEMORY_ADD_P(p))
                 put_num(loc, relocation + get_num(loc, bytes), bytes);
               break;
             }
         }
   #else
       switch (RELOC_TARGET_SIZE(p))        switch (RELOC_TARGET_SIZE(p))
         {          {
         case 0:          case 0:
           if (RELOC_MEMORY_SUB_P(p))            if (RELOC_MEMORY_SUB_P(p))
             relocation -= mask & *(char *) (data + addr);              relocation -= *(char *) (data + addr);
           else if (RELOC_MEMORY_ADD_P(p))            else if (RELOC_MEMORY_ADD_P(p))
             relocation += mask & *(char *) (data + addr);              relocation += *(char *) (data + addr);
           *(char *) (data + addr) &= ~mask;            *(char *) (data + addr) &= ~mask;
           *(char *) (data + addr) |= relocation;            *(char *) (data + addr) |= relocation & mask;
           break;            break;
   
         case 1:          case 1:
           if (RELOC_MEMORY_SUB_P(p))            if (RELOC_MEMORY_SUB_P(p))
             relocation -= mask & *(short *) (data + addr);              relocation -= *(short *) (data + addr);
           else if (RELOC_MEMORY_ADD_P(p))            else if (RELOC_MEMORY_ADD_P(p))
             relocation += mask & *(short *) (data + addr);              relocation += *(short *) (data + addr);
           *(short *) (data + addr) &= ~mask;            *(short *) (data + addr) &= ~mask;
           *(short *) (data + addr) |= relocation;            *(short *) (data + addr) |= relocation & mask;
           break;            break;
   
         case 2:          case 2:
   #ifdef CROSS_LINKER
             /* This is necessary if the host has stricter alignment
                than the target.  Too slow to use all the time.
                Also doesn't deal with differing byte-order.  */
             {
               /* Thing to relocate.  */
               long thing;
               bcopy (data + addr, &thing, sizeof (thing));
               if (RELOC_MEMORY_SUB_P (p))
                 relocation -= thing;
               else if (RELOC_MEMORY_ADD_P (p))
                 relocation += thing;
               thing = (thing & ~mask) | relocation & mask;
               bcopy (&thing, data + addr, sizeof (thing));
             }
   #else /* not CROSS_LINKER */
           if (RELOC_MEMORY_SUB_P(p))            if (RELOC_MEMORY_SUB_P(p))
             relocation -= mask & *(long *) (data + addr);              relocation -= *(long *) (data + addr);
           else if (RELOC_MEMORY_ADD_P(p))            else if (RELOC_MEMORY_ADD_P(p))
             relocation += mask & *(long *) (data + addr);              relocation += *(long *) (data + addr);
           *(long *) (data + addr) &= ~mask;            *(long *) (data + addr) &= ~mask;
           *(long *) (data + addr) |= relocation;            *(long *) (data + addr) |= relocation & mask;
   #endif /* not CROSS_LINKER */
           break;            break;
   
         default:          default:
           fatal_with_file ("Unimplemented relocation field length in ", entry);            fatal_with_file ("Unimplemented relocation field length in ", entry);
         }          }
   #endif /* MINIX */
     }      }
 }  }
   
 /* For relocatable_output only: write out the relocation,  /* For OUTPUT_RELOCATABLE only: write out the relocation,
    relocating the addresses-to-be-relocated.  */     relocating the addresses-to-be-relocated.  */
   
 void coptxtrel (), copdatrel ();  void coptxtrel (), copdatrel ();
Line 3823  write_rel () Line 5159  write_rel ()
         if (sp->referenced || sp->defined)          if (sp->referenced || sp->defined)
           {            {
             sp->def_count = count++;              sp->def_count = count++;
   #ifndef NeXT
             /* Leave room for the reference required by N_INDR, if              /* Leave room for the reference required by N_INDR, if
                necessary.  */                 necessary.  */
             if ((sp->defined & ~N_EXT) == N_INDR)              if ((sp->defined & ~N_EXT) == N_INDR)
               count++;                count++;
   #endif
           }            }
     }      }
   /* Correct, because if (reloatable_output), we will also be writing    /* Correct, because if (OUTPUT_RELOCATABLE), we will also be writing
      whatever indirect blocks we have.  */       whatever indirect blocks we have.  */
   #ifndef NeXT
   if (count != defined_global_sym_count    if (count != defined_global_sym_count
       + undefined_global_sym_count + global_indirect_count)        + undefined_global_sym_count + global_indirect_count)
   #else
     if (count != defined_global_sym_count
         + undefined_global_sym_count)
   #endif
     fatal ("internal error");      fatal ("internal error");
   
   /* Write out the relocations of all files, remembered from copy_text.  */    /* Write out the relocations of all files, remembered from copy_text.  */
   
   each_full_file (coptxtrel);    lseek (outdesc, output_trel_offset, 0);
     each_full_file (coptxtrel, 0);
   
   if (trace_files)    if (trace_files)
     fprintf (stderr, "\nWriting data relocation:\n\n");      fprintf (stderr, "\nWriting data relocation:\n\n");
   
   each_full_file (copdatrel);    lseek (outdesc, output_drel_offset, 0);
     each_full_file (copdatrel, 0);
   
   if (trace_files)    if (trace_files)
     fprintf (stderr, "\n");      fprintf (stderr, "\n");
Line 3853  coptxtrel (entry) Line 5198  coptxtrel (entry)
      struct file_entry *entry;       struct file_entry *entry;
 {  {
   register struct relocation_info *p, *end;    register struct relocation_info *p, *end;
   register int reloc = entry->text_start_address;    register int reloc = entry->text_start_address - text_start;
   
   p = entry->textrel;    p = entry->textrel;
   end = (struct relocation_info *) (entry->header.a_trsize + (char *) p);    end = (struct relocation_info *) (entry->text_reloc_size + (char *) p);
   while (p < end)    while (p < end)
     {      {
       RELOC_ADDRESS(p) += reloc;        RELOC_ADDRESS(p) += reloc;
Line 3868  coptxtrel (entry) Line 5213  coptxtrel (entry)
                               (((char *)entry->symbols) + symindex))                                (((char *)entry->symbols) + symindex))
                              ->n_un.n_name));                               ->n_un.n_name));
   
           if (symindex >= entry->header.a_syms)            if (symindex >= entry->syms_size)
             fatal_with_file ("relocation symbolnum out of range in ", entry);              fatal_with_file ("relocation symbolnum out of range in ", entry);
   
 #ifdef N_INDR  #ifdef N_INDR
Line 3883  coptxtrel (entry) Line 5228  coptxtrel (entry)
           if (symptr->defined)            if (symptr->defined)
             {              {
               RELOC_EXTERN_P(p) = 0;                RELOC_EXTERN_P(p) = 0;
               RELOC_SYMBOL(p) = (symptr->defined & N_TYPE);                RELOC_SYMBOL(p) = (symptr->defined & ~N_EXT);
 #ifdef RELOC_ADD_EXTRA  #ifdef RELOC_ADD_EXTRA
               /* If we aren't going to be adding in the value in                /* If we aren't going to be adding in the value in
                  memory on the next pass of the loader, then we need                   memory on the next pass of the loader, then we need
Line 3896  coptxtrel (entry) Line 5241  coptxtrel (entry)
           else            else
             /* Debugger symbols come first, so have to start this              /* Debugger symbols come first, so have to start this
                after them.  */                 after them.  */
   #ifndef NeXT
               RELOC_SYMBOL(p) = (symptr->def_count + nsyms                RELOC_SYMBOL(p) = (symptr->def_count + nsyms
                                  - defined_global_sym_count                                   - defined_global_sym_count
                                  - undefined_global_sym_count                                   - undefined_global_sym_count
                                  - global_indirect_count);                                   - global_indirect_count);
   #else
                 RELOC_SYMBOL(p) = (symptr->def_count + nsyms
                                    - defined_global_sym_count
                                    - undefined_global_sym_count);
   #endif
         }          }
       p++;        p++;
     }      }
   mywrite (entry->textrel, 1, entry->header.a_trsize, outdesc);  
   #ifdef MACH_O
     if (output_file_type == IS_MACH_O)
       generate_mach_o_relocations(entry->textrel,
                                   entry->text_reloc_size / sizeof (struct relocation_info));
   #endif
   
     mywrite (entry->textrel, 1, entry->text_reloc_size, outdesc);
 }  }
   
 void  void
Line 3913  copdatrel (entry) Line 5271  copdatrel (entry)
   register struct relocation_info *p, *end;    register struct relocation_info *p, *end;
   /* Relocate the address of the relocation.    /* Relocate the address of the relocation.
      Old address is relative to start of the input file's data section.       Old address is relative to start of the input file's data section.
      New address is relative to start of the output file's data section.  */       New address is relative to start of the output file's data section.
   register int reloc = entry->data_start_address - text_size;  
        So the amount we need to relocate it by is the offset of this
        input file's data section within the output file's data section.  */
     register int reloc = entry->data_start_address - data_start;
   
   p = entry->datarel;    p = entry->datarel;
   end = (struct relocation_info *) (entry->header.a_drsize + (char *) p);    end = (struct relocation_info *) (entry->data_reloc_size + (char *) p);
   while (p < end)    while (p < end)
     {      {
       RELOC_ADDRESS(p) += reloc;        RELOC_ADDRESS(p) += reloc;
Line 3930  copdatrel (entry) Line 5291  copdatrel (entry)
                              ->n_un.n_name));                               ->n_un.n_name));
           int symtype;            int symtype;
   
           if (symindex >= entry->header.a_syms)            if (symindex >= entry->syms_size)
             fatal_with_file ("relocation symbolnum out of range in ", entry);              fatal_with_file ("relocation symbolnum out of range in ", entry);
   
 #ifdef N_INDR  #ifdef N_INDR
Line 3939  copdatrel (entry) Line 5300  copdatrel (entry)
             symptr = (symbol *) symptr->value;              symptr = (symbol *) symptr->value;
 #endif  #endif
   
            symtype = symptr->defined & N_TYPE;            symtype = symptr->defined & ~N_EXT;
   
           if (force_common_definition            if (force_common_definition
               || symtype == N_DATA || symtype == N_TEXT || symtype == N_ABS)                || symtype == N_DATA || symtype == N_TEXT || symtype == N_ABS)
Line 3950  copdatrel (entry) Line 5311  copdatrel (entry)
           else            else
             /* Debugger symbols come first, so have to start this              /* Debugger symbols come first, so have to start this
                after them.  */                 after them.  */
   #ifndef NeXT
             RELOC_SYMBOL(p)              RELOC_SYMBOL(p)
               = (((symbol *)                = (((symbol *)
                   (((struct nlist *)                    (((struct nlist *)
Line 3959  copdatrel (entry) Line 5321  copdatrel (entry)
                  + nsyms - defined_global_sym_count                   + nsyms - defined_global_sym_count
                  - undefined_global_sym_count                   - undefined_global_sym_count
                  - global_indirect_count);                   - global_indirect_count);
   #else
               RELOC_SYMBOL(p)
                 = (((symbol *)
                     (((struct nlist *)
                       (((char *)entry->symbols) + symindex))
                      ->n_un.n_name))
                    ->def_count
                    + nsyms - defined_global_sym_count
                    - undefined_global_sym_count);
   #endif
         }          }
       p++;        p++;
     }      }
   mywrite (entry->datarel, 1, entry->header.a_drsize, outdesc);  #ifdef MACH_O
     if (output_file_type == IS_MACH_O)
       generate_mach_o_relocations(entry->datarel,
                                   entry->data_reloc_size / sizeof (struct relocation_info));
   #endif
   
     mywrite (entry->datarel, 1, entry->data_reloc_size, outdesc);
 }  }
   
 void write_file_syms ();  void write_file_syms ();
 void write_string_table ();  void write_string_table ();
   
 /* Offsets and current lengths of symbol and string tables in output file. */  
   
 int symbol_table_offset;  
 int symbol_table_len;  
   
 /* Address in output file where string table starts.  */  
 int string_table_offset;  
   
 /* Offset within string table  
    where the strings in `strtab_vector' should be written.  */  
 int string_table_len;  
   
 /* Total size of string table strings allocated so far,  /* Total size of string table strings allocated so far,
    including strings in `strtab_vector'.  */     including strings in `strtab_vector'.  */
 int strtab_size;  int strtab_size;
Line 4022  write_string_table () Line 5388  write_string_table ()
 {  {
   register int i;    register int i;
   
   lseek (outdesc, string_table_offset + string_table_len, 0);    lseek (outdesc, output_strs_offset + output_strs_size, 0);
   
   if (!outstream)    if (!outstream)
     outstream = fdopen (outdesc, "w");      outstream = fdopen (outdesc, "w");
Line 4030  write_string_table () Line 5396  write_string_table ()
   for (i = 0; i < strtab_index; i++)    for (i = 0; i < strtab_index; i++)
     {      {
       fwrite (strtab_vector[i], 1, strtab_lens[i], outstream);        fwrite (strtab_vector[i], 1, strtab_lens[i], outstream);
       string_table_len += strtab_lens[i];        output_strs_size += strtab_lens[i];
     }      }
   
   fflush (outstream);    fflush (outstream);
Line 4054  write_syms () Line 5420  write_syms ()
      extra struct for each indirect symbol to hold the extra reference       extra struct for each indirect symbol to hold the extra reference
      following. */       following. */
   struct nlist *buf    struct nlist *buf
   #ifndef NeXT
     = (struct nlist *) alloca ((defined_global_sym_count      = (struct nlist *) alloca ((defined_global_sym_count
                                 + undefined_global_sym_count                                  + undefined_global_sym_count
                                 + global_indirect_count)                                  + global_indirect_count)
                                * sizeof (struct nlist));                                 * sizeof (struct nlist));
   #else
       = (struct nlist *) alloca ((defined_global_sym_count
                                   + undefined_global_sym_count)
                                  * sizeof (struct nlist));
   #endif
   /* Pointer for storing into BUF.  */    /* Pointer for storing into BUF.  */
   register struct nlist *bufp = buf;    register struct nlist *bufp = buf;
   
   /* Size of string table includes the bytes that store the size.  */    /* Size of string table includes the bytes that store the size.  */
   strtab_size = sizeof strtab_size;    strtab_size = sizeof strtab_size;
   
   symbol_table_offset = N_SYMOFF (outheader);    output_syms_size = 0;
   symbol_table_len = 0;    output_strs_size = strtab_size;
   string_table_offset = N_STROFF (outheader);  
   string_table_len = strtab_size;  
   
   if (strip_symbols == STRIP_ALL)    if (strip_symbols == STRIP_ALL)
     return;      return;
Line 4096  write_syms () Line 5466  write_syms ()
       {        {
         struct nlist nl;          struct nlist nl;
   
   #ifdef N_SECT
           nl.n_sect = 0;
   #else
         nl.n_other = 0;          nl.n_other = 0;
   #endif
         nl.n_desc = 0;          nl.n_desc = 0;
   
         /* Compute a `struct nlist' for the symbol.  */          /* Compute a `struct nlist' for the symbol.  */
Line 4111  write_syms () Line 5485  write_syms ()
                 /* If the target of an indirect symbol has been                  /* If the target of an indirect symbol has been
                    defined and we are outputting an executable,                     defined and we are outputting an executable,
                    resolve the indirection; it's no longer needed */                     resolve the indirection; it's no longer needed */
                 if (!relocatable_output                  if (output_style != OUTPUT_RELOCATABLE
                     && ((sp->defined & N_TYPE) == N_INDR)                      && ((sp->defined & ~N_EXT) == N_INDR)
                     && (((symbol *) sp->value)->defined > 1))                      && (((symbol *) sp->value)->defined > 1))
                   {                    {
                     symbol *newsp = (symbol *) sp->value;                      symbol *newsp = (symbol *) sp->value;
Line 4152  write_syms () Line 5526  write_syms ()
             *bufp++ = nl;              *bufp++ = nl;
             syms_written++;              syms_written++;
             if (nl.n_type == (N_INDR | N_EXT))              if (nl.n_type == (N_INDR | N_EXT))
   #ifndef NeXT
               {                {
                 struct nlist xtra_ref;                  struct nlist xtra_ref;
                 xtra_ref.n_type == N_EXT | N_UNDF;                  xtra_ref.n_type == N_EXT | N_UNDF;
                 xtra_ref.n_un.n_strx                  xtra_ref.n_un.n_strx
                   = assign_string_table_index (((symbol *) sp->value)->name);                    = assign_string_table_index (((symbol *) sp->value)->name);
   #ifdef N_SECT
                   xtra_ref.n_sect = 0;
   #else
                 xtra_ref.n_other = 0;                  xtra_ref.n_other = 0;
   #endif
                 xtra_ref.n_desc = 0;                  xtra_ref.n_desc = 0;
                 xtra_ref.n_value = 0;                  xtra_ref.n_value = 0;
                 *bufp++ = xtra_ref;                  *bufp++ = xtra_ref;
                 syms_written++;                  syms_written++;
               }                }
   #else
               nl.n_value = assign_string_table_index (((symbol *) sp->value)->name);
   #endif
           }            }
       }        }
   
   #ifdef MACH_O
     if (output_file_type == IS_MACH_O)
       generate_mach_o_symbols(buf, bufp - buf);
   #endif
   
   /* Output the buffer full of `struct nlist's.  */    /* Output the buffer full of `struct nlist's.  */
   
   lseek (outdesc, symbol_table_offset + symbol_table_len, 0);    lseek (outdesc, output_syms_offset + output_syms_size, 0);
   mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);    mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);
   symbol_table_len += sizeof (struct nlist) * (bufp - buf);    output_syms_size += sizeof (struct nlist) * (bufp - buf);
   
   if (syms_written != nsyms)    if (syms_written != nsyms)
     fatal ("internal error: wrong number of symbols written into output file", 0);      fatal ("internal error: wrong number of symbols written into output file", 0);
   
   if (symbol_table_offset + symbol_table_len != string_table_offset)    /* Now the total string table size is known, so write it into the
     fatal ("internal error: inconsistent symbol table length", 0);       first word of the string table.  */
   
   /* Now the total string table size is known, so write it.  
      We are already positioned at the right place in the file.  */  
   
   mywrite (&strtab_size, sizeof (int), 1, outdesc);  /* we're at right place */    lseek (outdesc, output_strs_offset, 0);
     mywrite (&strtab_size, sizeof (int), 1, outdesc);
   
   /* Write the strings for the global symbols.  */    /* Write the strings for the global symbols.  */
   
Line 4200  write_file_syms (entry, syms_written_add Line 5585  write_file_syms (entry, syms_written_add
      int *syms_written_addr;       int *syms_written_addr;
 {  {
   register struct nlist *p = entry->symbols;    register struct nlist *p = entry->symbols;
   register struct nlist *end = p + entry->header.a_syms / sizeof (struct nlist);    register struct nlist *end = p + entry->syms_size / sizeof (struct nlist);
   
   /* Buffer to accumulate all the syms before writing them.    /* Buffer to accumulate all the syms before writing them.
      It has one extra slot for the local symbol we generate here.  */       It has one extra slot for the local symbol we generate here.  */
   struct nlist *buf    struct nlist *buf
     = (struct nlist *) alloca (entry->header.a_syms + sizeof (struct nlist));      = (struct nlist *) alloca (entry->syms_size + sizeof (struct nlist));
   register struct nlist *bufp = buf;    register struct nlist *bufp = buf;
   
   /* Upper bound on number of syms to be written here.  */    /* Upper bound on number of syms to be written here.  */
   int max_syms = (entry->header.a_syms / sizeof (struct nlist)) + 1;    int max_syms = (entry->syms_size / sizeof (struct nlist)) + 1;
   
   /* Make tables that record, for each symbol, its name and its name's length.    /* Make tables that record, for each symbol, its name and its name's length.
      The elements are filled in by `assign_string_table_index'.  */       The elements are filled in by `assign_string_table_index'.  */
Line 4220  write_file_syms (entry, syms_written_add Line 5605  write_file_syms (entry, syms_written_add
   
   /* Generate a local symbol for the start of this file's text.  */    /* Generate a local symbol for the start of this file's text.  */
   
   #ifndef OFILE_FN_FLAGGED
   if (discard_locals != DISCARD_ALL)    if (discard_locals != DISCARD_ALL)
   #endif
     {      {
       struct nlist nl;        struct nlist nl;
   
   #ifndef OFILE_FN_FLAGGED
       nl.n_type = N_TEXT;        nl.n_type = N_TEXT;
   #else
         nl.n_type = N_FN | N_EXT;
   #endif
       nl.n_un.n_strx = assign_string_table_index (entry->local_sym_name);        nl.n_un.n_strx = assign_string_table_index (entry->local_sym_name);
       nl.n_value = entry->text_start_address;        nl.n_value = entry->text_start_address;
       nl.n_desc = 0;        nl.n_desc = 0;
   #ifdef N_SECT
         nl.n_sect = 0;
   #else
       nl.n_other = 0;        nl.n_other = 0;
   #endif
       *bufp++ = nl;        *bufp++ = nl;
       (*syms_written_addr)++;        (*syms_written_addr)++;
       entry->local_syms_offset = *syms_written_addr * sizeof (struct nlist);        entry->local_syms_offset = *syms_written_addr * sizeof (struct nlist);
Line 4236  write_file_syms (entry, syms_written_add Line 5631  write_file_syms (entry, syms_written_add
   
   /* Read the file's string table.  */    /* Read the file's string table.  */
   
   entry->strings = (char *) alloca (entry->string_size);    entry->strings = (char *) alloca (entry->strs_size);
   read_entry_strings (file_open (entry), entry);    read_entry_strings (file_open (entry), entry);
   
   for (; p < end; p++)    for (; p < end; p++)
Line 4251  write_file_syms (entry, syms_written_add Line 5646  write_file_syms (entry, syms_written_add
                                 /* types of symbols are never written */                                  /* types of symbols are never written */
                                 /* globally, though they are stored */                                  /* globally, though they are stored */
                                 /* globally.  */                                  /* globally.  */
         write = relocatable_output;          write = output_style == OUTPUT_RELOCATABLE;
       else if (!(type & (N_STAB | N_EXT)))        else if (!(type & (N_STAB | N_EXT)))
         /* ordinary local symbol */          /* ordinary local symbol */
         write = ((discard_locals != DISCARD_ALL)          write = ((discard_locals != DISCARD_ALL)
Line 4278  write_file_syms (entry, syms_written_add Line 5673  write_file_syms (entry, syms_written_add
         }          }
     }      }
   
   #ifdef MACH_O
     if (output_file_type == IS_MACH_O)
       generate_mach_o_symbols(buf, bufp - buf);
   #endif
   
   /* All the symbols are now in BUF; write them.  */    /* All the symbols are now in BUF; write them.  */
   
   lseek (outdesc, symbol_table_offset + symbol_table_len, 0);    lseek (outdesc, output_syms_offset + output_syms_size, 0);
   mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);    mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);
   symbol_table_len += sizeof (struct nlist) * (bufp - buf);    output_syms_size += sizeof (struct nlist) * (bufp - buf);
   
   /* Write the string-table data for the symbols just written,    /* Write the string-table data for the symbols just written,
      using the data in vectors `strtab_vector' and `strtab_lens'.  */       using the data in vectors `strtab_vector' and `strtab_lens'.  */
Line 4300  void write_file_symseg (); Line 5700  void write_file_symseg ();
 void  void
 write_symsegs ()  write_symsegs ()
 {  {
     lseek (outdesc, output_symseg_offset, 0);
   each_file (write_file_symseg, 0);    each_file (write_file_symseg, 0);
 }  }
   
Line 4309  write_file_symseg (entry) Line 5710  write_file_symseg (entry)
 {  {
   char buffer[4096];    char buffer[4096];
   struct symbol_root root;    struct symbol_root root;
   int indesc;    int indesc, len, total;
   int len;  
   
   if (entry->symseg_offset == 0)    if (entry->symseg_size == 0)
     return;      return;
   
     output_symseg_size += entry->symseg_size;
   
   /* This entry has a symbol segment.  Read the root of the segment.  */    /* This entry has a symbol segment.  Read the root of the segment.  */
   
   indesc = file_open (entry);    indesc = file_open (entry);
Line 4325  write_file_symseg (entry) Line 5727  write_file_symseg (entry)
   /* Store some relocation info into the root.  */    /* Store some relocation info into the root.  */
   
   root.ldsymoff = entry->local_syms_offset;    root.ldsymoff = entry->local_syms_offset;
   root.textrel = entry->text_start_address;    root.textrel = entry->text_start_address - entry->orig_text_address;
   root.datarel = entry->data_start_address - entry->header.a_text;    root.datarel = entry->data_start_address - entry->orig_data_address;
   root.bssrel = entry->bss_start_address    root.bssrel = entry->bss_start_address - entry->orig_bss_address;
     - entry->header.a_text - entry->header.a_data;  
   root.databeg = entry->data_start_address - root.datarel;    root.databeg = entry->data_start_address - root.datarel;
   root.bssbeg = entry->bss_start_address - root.bssrel;    root.bssbeg = entry->bss_start_address - root.bssrel;
   
Line 4338  write_file_symseg (entry) Line 5739  write_file_symseg (entry)
   
   /* Copy the rest of the symbol segment unchanged.  */    /* Copy the rest of the symbol segment unchanged.  */
   
   if (entry->superfile)    total = entry->symseg_size - sizeof root;
     {  
       /* Library member: number of bytes to copy is determined  
          from the member's total size.  */  
   
       int total = entry->total_size - entry->symseg_offset - sizeof root;  
   
       while (total > 0)    while (total > 0)
         {  
           len = read (indesc, buffer, min (sizeof buffer, total));  
   
           if (len != min (sizeof buffer, total))  
             fatal_with_file ("premature end of file in symbol segment of ", entry);  
           total -= len;  
           mywrite (buffer, len, 1, outdesc);  
         }  
     }  
   else  
     {      {
       /* A separate file: copy until end of file.  */        len = read (indesc, buffer, min (sizeof buffer, total));
   
       while (len = read (indesc, buffer, sizeof buffer))        if (len != min (sizeof buffer, total))
         {          fatal_with_file ("premature end of file in symbol segment of ", entry);
           mywrite (buffer, len, 1, outdesc);        total -= len;
           if (len < sizeof buffer)        mywrite (buffer, len, 1, outdesc);
             break;  
         }  
     }      }
   
   file_close ();    file_close ();
 }  }
   
   /* Define a special symbol (etext, edata, or end).  NAME is the
      name of the symbol, with a leading underscore (whether or not this
      system uses such underscores).  TYPE is its type (e.g. N_DATA | N_EXT).
      Store a symbol * for the symbol in *SYM if SYM is non-NULL.  */
   static void
   symbol_define (name, type, sym)
        /* const */ char *name;
        int type;
        symbol **sym;
   {
     symbol *thesym;
   
   #if defined(nounderscore)
     /* Skip the leading underscore.  */
     name++;
   #endif
   
     thesym = getsym (name);
     if (thesym->defined)
       {
         /* The symbol is defined in some input file.  Don't mess with it.  */
         if (sym)
           *sym = 0;
       }
     else
       {
         if (thesym->referenced)
           /* The symbol was not defined, and we are defining it now.  */
           undefined_global_sym_count--;
         thesym->defined = type;
         thesym->referenced = 1;
         if (sym)
           *sym = thesym;
       }
   }
   
 /* Create the symbol table entries for `etext', `edata' and `end'.  */  /* Create the symbol table entries for `etext', `edata' and `end'.  */
   
 void  void
 symtab_init ()  symtab_init ()
 {  {
 #ifndef nounderscore    symbol_define ("_edata", N_DATA | N_EXT, &edata_symbol);
   edata_symbol = getsym ("_edata");    symbol_define ("_etext", N_TEXT | N_EXT, &etext_symbol);
   etext_symbol = getsym ("_etext");    symbol_define ("_end", N_BSS | N_EXT, &end_symbol);
   end_symbol = getsym ("_end");  
 #else    /* Either _edata or __edata (C names) is OK as far as ANSI is concerned
   edata_symbol = getsym ("edata");       (see section 4.1.2.1).  In general, it is best to use __foo and
   etext_symbol = getsym ("etext");       not worry about the confusing rules for the _foo namespace.
   end_symbol = getsym ("end");       But HPUX 7.0 uses _edata, so we might as weel be consistent.  */
 #endif    symbol_define ("__edata", N_DATA | N_EXT, &edata_symbol_alt);
     symbol_define ("__etext", N_TEXT | N_EXT, &etext_symbol_alt);
     symbol_define ("__end", N_BSS | N_EXT, &end_symbol_alt);
   
 #ifdef sun  #ifdef sun
   {    {
     symbol *dynamic_symbol = getsym ("__DYNAMIC");      symbol *dynamic_symbol;
     dynamic_symbol->defined = N_ABS | N_EXT;      symbol_define ("__DYNAMIC", N_ABS | N_EXT, &dynamic_symbol);
     dynamic_symbol->referenced = 1;      if (dynamic_symbol)
     dynamic_symbol->value = 0;        dynamic_symbol->value = 0;
   }    }
 #endif  #endif
 #ifdef sequent  #ifdef sequent
   {    {
     symbol *_387_flt_symbol = getsym ("_387_flt");      symbol *i387_flt_symbol;
     _387_flt_symbol->defined = N_ABS | N_EXT;      symbol_define ("_387_flt", N_ABS | N_EXT, &i387_flt_symbol);
     _387_flt_symbol->referenced = 1;      if (i387_flt_symbol)
     _387_flt_symbol->value = 0;        i387_flt_symbol->value = 0;
     }
   #endif
   #ifdef NeXT
     {
       symbol *shlib_init_symbol;
       symbol_define ("__shared_library_initialization", N_UNDF | N_EXT, &shlib_init_symbol);
       if (shlib_init_symbol)
         shlib_init_symbol->max_common_size = sizeof (long int);
   }    }
 #endif  #endif
   
   edata_symbol->defined = N_DATA | N_EXT;  
   etext_symbol->defined = N_TEXT | N_EXT;  
   end_symbol->defined = N_BSS | N_EXT;  
   
   edata_symbol->referenced = 1;  
   etext_symbol->referenced = 1;  
   end_symbol->referenced = 1;  
 }  }
   
 /* Compute the hash code for symbol name KEY.  */  /* Compute the hash code for symbol name KEY.  */
Line 4462  getsym (key) Line 5884  getsym (key)
   bp->warning = 0;    bp->warning = 0;
   bp->undef_refs = 0;    bp->undef_refs = 0;
   bp->multiply_defined = 0;    bp->multiply_defined = 0;
     bp->last_library_ref = 0;
   
   /* Add the entry to the bucket.  */    /* Add the entry to the bucket.  */
   
Line 4495  getsym_soft (key) Line 5918  getsym_soft (key)
   return 0;    return 0;
 }  }
   
   /* Report a usage error.
      Like fatal except prints a usage summary.  */
   
   void
   usage (string, arg)
        char *string, *arg;
   {
     if (string)
       {
         fprintf (stderr, "%s: ", progname);
         fprintf (stderr, string, arg);
         fprintf (stderr, "\n");
       }
     fprintf (stderr, "\
   Usage: %s [-d] [-dc] [-dp] [-e symbol] [-l lib] [-n] [-noinhibit-exec]\n\
          [-nostdlib] [-o file] [-r] [-s] [-t] [-u symbol] [-x] [-y symbol]\n\
          [-z] [-A file] [-Bstatic] [-D size] [-L libdir] [-M] [-N]\n\
          [-S] [-T[{text,data}] addr] [-V prefix] [-X] [file...]\n",
              progname);
     exit (1);
   }
   
 /* Report a fatal error.  /* Report a fatal error.
    STRING is a printf format string and ARG is one arg for it.  */     STRING is a printf format string and ARG is one arg for it.  */
   
Line 4502  void Line 5947  void
 fatal (string, arg)  fatal (string, arg)
      char *string, *arg;       char *string, *arg;
 {  {
   fprintf (stderr, "ld: ");    fprintf (stderr, "%s: ", progname);
   fprintf (stderr, string, arg);    fprintf (stderr, string, arg);
   fprintf (stderr, "\n");    fprintf (stderr, "\n");
   exit (1);    exit (1);
Line 4516  fatal_with_file (string, entry) Line 5961  fatal_with_file (string, entry)
      char *string;       char *string;
      struct file_entry *entry;       struct file_entry *entry;
 {  {
   fprintf (stderr, "ld: ");    fprintf (stderr, "%s: ", progname);
   fprintf (stderr, string);    fprintf (stderr, string);
   print_file_name (entry, stderr);    print_file_name (entry, stderr);
   fprintf (stderr, "\n");    fprintf (stderr, "\n");
Line 4646  parse (arg, format, error) Line 6091  parse (arg, format, error)
   
 /* Like malloc but get fatal error if memory is exhausted.  */  /* Like malloc but get fatal error if memory is exhausted.  */
   
 int  char *
 xmalloc (size)  xmalloc (size)
      int size;       int size;
 {  {
   register int result = malloc (size);    register char *result = malloc (size);
   if (!result)    if (!result)
     fatal ("virtual memory exhausted", 0);      fatal ("virtual memory exhausted", 0);
   return result;    return result;
Line 4658  xmalloc (size) Line 6103  xmalloc (size)
   
 /* Like realloc but get fatal error if memory is exhausted.  */  /* Like realloc but get fatal error if memory is exhausted.  */
   
 int  char *
 xrealloc (ptr, size)  xrealloc (ptr, size)
      char *ptr;       char *ptr;
      int size;       int size;
 {  {
   register int result = realloc (ptr, size);    register char *result = realloc (ptr, size);
   if (!result)    if (!result)
     fatal ("virtual memory exhausted", 0);      fatal ("virtual memory exhausted", 0);
   return result;    return result;
Line 4691  getpagesize () Line 6136  getpagesize ()
 }  }
   
 #endif  #endif
   #ifdef ns32000
   /* code by Ian Dall for the ns32k */
   /* Just put out the twos complement value with arbitrary alignment could
    * just do an assignment if we know we are on a little endian. */
   void put_num(buf,val,n)
        char       *buf;
        long       val;
        char       n;
   { 
     for (; n > 0; n--)
       {
         *buf++ = val & 0xff; val >>= 8;
       }
   }
   
   int get_num(buf, n)
        char *buf;
        int n;
   {
     int val = 0;
     buf += (n - 1);
     for (; n > 0; n--)
       {
         val = val * 256 + (*buf-- & 0xff);
       }
     return val;
   }
   
   /* Immediate operands are bigendian */
   void put_imm(buf,val,n)
        char       *buf;
        long       val;
        char       n;
   { 
     int i;
     buf += (n - 1);
     for (i = n - 1; i >= 0; i--)
       {
         *buf-- = (val & 0xff); val >>= 8;
       }
   }
   
   int get_imm(buf, n)
        char *buf;
        int n;
   {
     int val = 0;
     for (; n > 0; n--)
       {
         val = (val * 256) + (*buf++ & 0xff);
       }
     return val;
   }
   
   /* This converts an integer "val" to a displacement. The reason for its'
      existence is the fact that ns32k uses Huffman coded displacements.
      This implies that the bit order is reversed in displacements and
      that they are prefixed with a size-tag.
   
      binary: msb -> lsb   0xxxxxxx                                byte
                           10xxxxxx xxxxxxxx                       word
                           11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx     double word
             
      This must be taken care of and we do it here!                  
    */
   void put_disp(buf,val,n)
        char       *buf;
        long       val;
        char       n;
   { 
     switch(n) {
     case 1:
       if (val < -64 || val > 63)
         fprintf(stderr,"Byte displacement %d, out of range.\n", val);
       val&=0x7f;
   #ifdef SHOW_NUM
                   printf("%x ",val & 0xff);
   #endif
       *buf++=val;
       break;
     case 2:
       if (val < -8192 || val > 8191)
         fprintf(stderr,"Word displacement %d, out of range.\n", val);
       val&=0x3fff;
       val|=0x8000;
   #ifdef SHOW_NUM
                   printf("%x ",val>>8 & 0xff);
   #endif
       *buf++=(val>>8);
   #ifdef SHOW_NUM
                   printf("%x ",val & 0xff);
   #endif
       *buf++=val;
       break;
     case 4:
       if (val < -0x1f000000 || val >= 0x20000000)
       /* if (val < -0x20000000 || val >= 0x20000000) */
         fprintf(stderr,"Double word displacement %d, out of range\n", val);
       val|=0xc0000000;
   #ifdef SHOW_NUM
                   printf("%x ",val>>24 & 0xff);
   #endif
       *buf++=(val>>24);
   #ifdef SHOW_NUM
                   printf("%x ",val>>16 & 0xff);
   #endif
       *buf++=(val>>16);
   #ifdef SHOW_NUM
                   printf("%x ",val>>8 & 0xff);
   #endif
       *buf++=(val>>8);
   #ifdef SHOW_NUM
                   printf("%x ",val & 0xff);
   #endif
       *buf++=val;
       break;
     default:
       error("Internal logic error");
     }
   }
   
   int sign_extend (value, bits)
        int value, bits;
   {
     value = value & ((1 << bits) - 1);
     return (value & (1 << (bits-1))
             ? value | (~((1 << bits) - 1))
             : value);
   }
   
   int get_disp (buffer, n)
        char *buffer;
        int n;
   {
     int Ivalue;
   
     Ivalue = *buffer++ & 0xff;
     if (n == 0)
       if (Ivalue & 0x80)
         if (Ivalue & 0x40)
           n = 4;
         else
           n = 2;
       else
         n = 1;
     switch (n)
       {
       case 1:
         Ivalue = sign_extend (Ivalue, 7);
         break;
       case 2:
         Ivalue = sign_extend (Ivalue, 6);
         Ivalue = (Ivalue << 8) | (0xff & *buffer);
         break;
       case 4:
         Ivalue = sign_extend (Ivalue, 6);
         Ivalue = (Ivalue << 8) | (0xff & *buffer++);
         Ivalue = (Ivalue << 8) | (0xff & *buffer++);
         Ivalue = (Ivalue << 8) | (0xff & *buffer);
         break;
       default:
         fprintf(stderr, "get_disp: invalid argument\n");
       }
     return Ivalue;
   }
   #endif
   
   #if defined(sun) && defined(sparc)
   int
   getpagesize ()
   {
     return 8192;
   }
   #endif

Removed from v.1.1.1.5  
changed lines
  Added in v.1.1.1.6


unix.superglobalmegacorp.com