Added new keyword 'CONSTRUCTORS'
authorSteve Chamberlain <steve@cygnus>
Thu, 1 Aug 1991 23:29:23 +0000 (23:29 +0000)
committerSteve Chamberlain <steve@cygnus>
Thu, 1 Aug 1991 23:29:23 +0000 (23:29 +0000)
Added N_WARNING handling
Added N_INDR handling

ld/ldgld.script
ld/ldgldUr.script
ld/ldlang.c
ld/ldmain.c
ld/ldsym.c
ld/ldsym.h
ld/ldwarn.h

index 2f402c1324f3258b93631ccb52ccd773afb12ea2..15ff71fc383ad4c6dc3fc3a8305665ae8884742e 100755 (executable)
@@ -7,21 +7,23 @@ __DYNAMIC = 0;
 SECTIONS                               
 {                                      
   .text 0x2020 BLOCK(0x2000):          
-  {                                    
-   CREATE_OBJECT_SYMBOLS               
-    *(.text)                           
-    _etext = ALIGN( 0x2000);           
+    {                                  
+      CREATE_OBJECT_SYMBOLS            ;
+      *(.text);                                
+      _etext = ALIGN( 0x2000);         
     }                                          
   .data  ALIGN(0x2000)  :              
-  {                                    
-    *(.data)                           
+    {                                  
+      *(.data);                                
+      CONSTRUCTORS;
       _edata  =  .;                    
-  }                                    
+    }                                          
   .bss   SIZEOF(.data) + ADDR(.data) : 
-  {                                    
-   *(.bss)                             
-   [COMMON]                            
-     _end = .;                         
+    {                                  
+      *(.bss)                          
+       [COMMON]                                
+         _end = .;                             
+      __end = .;                               
     }                                  
 }
 
index 3871454f8d3639c516ac836eca4d8d9a27ddf90e..e7d9b4470514a4facf83d188ae0006cc59a99bed 100755 (executable)
@@ -12,14 +12,7 @@ SECTIONS
   .data SIZEOF(.text) + ADDR(.text) :  
   {                                    
     *(.data)                           
-    ___DTOR_LIST__ = . ;                       
-    LONG((___CTOR_LIST__ - .) / 4 -2)          
-    *(___DTOR_LIST__)                   
-    LONG(0)                             
-    ___CTOR_LIST__ = . ;                       
-    LONG((___end_list__  - .) / 4 -2)     
-    *(___CTOR_LIST__)                   
-    LONG(0)                             
+       CONSTRUCTORS
     ___end_list__  =  . ;                      
     }                                  
   .bss SIZEOF(.data) + ADDR(.data) :   
index 1ffad73e5048026f6247eb50feeb8184dcc3e6ae..5a65b0ee45be924e7a1c07e2fc3cc423fb1b66c9 100644 (file)
@@ -29,7 +29,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "ldmain.h"
 #include "ldsym.h"
 #include "ldgram.h"
-
+#include "ldwarn.h"
 #include "ldlang.h"
 #include "ldexp.h"
 #include "ldemul.h"
@@ -44,6 +44,14 @@ PROTO(static void, print_statement,(lang_statement_union_type *,
 /* LOCALS */
 static CONST  char *startup_file;
 static lang_statement_list_type input_file_chain;
+
+/* Points to the last statement in the .data section, so we can add
+   stuff to the data section without pain */
+static lang_statement_list_type end_of_data_section_statement_list;
+
+/* List of statements needed to handle consxtructors */
+static lang_statement_list_type constructor_list;
+
 static boolean placed_commons = false;
 static lang_output_section_statement_type *default_common_section;
 static boolean map_option_f;
@@ -97,6 +105,8 @@ extern boolean write_map;
 
 #define outside_symbol_address(q) ((q)->value +   outside_section_address(q->section))
 
+static void EXFUN(lang_add_data,( int type ,   union etree_union *exp));
+
 static void 
 DEFUN(print_size,(value),
       size_t value)
@@ -139,6 +149,9 @@ DEFUN(lang_for_each_statement_worker,(func,  s),
        func(s);
 
        switch (s->header.type) {
+       case lang_constructors_statement_enum:
+         lang_for_each_statement_worker(func, constructor_list.head);
+         break;
        case lang_output_section_statement_enum:
          lang_for_each_statement_worker
            (func, 
@@ -839,13 +852,19 @@ DEFUN(map_input_to_output_sections,(s, target, output_section_statement),
   for (; s != (lang_statement_union_type *)NULL ; s = s->next) 
     {
       switch (s->header.type) {
+
+
       case lang_wild_statement_enum:
        wild(&s->wild_statement, s->wild_statement.section_name,
             s->wild_statement.filename, target,
             output_section_statement);
 
        break;
-
+      case lang_constructors_statement_enum:
+       map_input_to_output_sections(constructor_list.head,
+                                    target,
+                                    output_section_statement);
+       break;
       case lang_output_section_statement_enum:
        map_input_to_output_sections(s->output_section_statement.children.head,
                        target,
@@ -1135,6 +1154,11 @@ DEFUN(print_statement,(s, os),
 {
   while (s) {
     switch (s->header.type) {
+    case lang_constructors_statement_enum:
+      printf("constructors:\n");
+print_statement(constructor_list.head, os);
+break; 
+
     case lang_wild_statement_enum:
       print_wild_statement(&s->wild_statement, os);
       break;
@@ -1297,6 +1321,8 @@ DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, dot),
   for (; s != (lang_statement_union_type *)NULL ; s = s->next) 
       {
        switch (s->header.type) {
+
+         
        case lang_output_section_statement_enum:
            {
              bfd_vma after;
@@ -1355,7 +1381,14 @@ DEFUN(lang_size_sections,(s, output_section_statement, prev, fill, dot),
            }
 
          break;
-
+       case lang_constructors_statement_enum:
+           dot = lang_size_sections(constructor_list.head,
+                                     output_section_statement,
+                                     &s->wild_statement.children.head,
+                                     fill,
+                                     dot);
+           break;
+                                     
        case lang_data_statement_enum: 
            {
              unsigned int size;
@@ -1464,6 +1497,13 @@ DEFUN(lang_do_assignments,(s, output_section_statement, fill, dot),
   for (; s != (lang_statement_union_type *)NULL ; s = s->next) 
     {
       switch (s->header.type) {
+      case lang_constructors_statement_enum:
+       dot = lang_do_assignments(constructor_list.head,
+                           output_section_statement,
+                           fill,
+                           dot);
+       break;
+
       case lang_output_section_statement_enum:
        {
          lang_output_section_statement_type *os =
@@ -1576,7 +1616,15 @@ DEFUN_VOID(lang_relocate_globals)
     }
     if (it != (asymbol *)NULL)
        {
-         asymbol **ptr= lgs->srefs_chain;
+         asymbol **ptr = lgs->srefs_chain;;
+         if (lgs->flags & SYM_WARNING) 
+             {
+               produce_warnings(lgs, it);
+             }
+         if (lgs->flags & SYM_INDIRECT)
+             {
+               do_indirect(lgs);
+             }
 
          while (ptr != (asymbol **)NULL) {
            asymbol *ref = *ptr;
@@ -1938,7 +1986,8 @@ DEFUN(lang_enter_output_section_statement,
     os =
       lang_output_section_statement_lookup(output_section_statement_name);
 
-
+  
+  
   /* Add this statement to tree */
   /*  add_statement(lang_output_section_statement_enum,
       output_section_statement);*/
@@ -1989,7 +2038,88 @@ DEFUN(create_symbol,(name, flags, section),
   return def;
 }
 
+/* run through the symbol table, find all the symbols which are
+   constructors and for each one, create statements to do something
+   like..
+
+   for 
+   __CTOR_LIST__, foo
+
+   __CTOR_LIST__ = . ;
+   LONG(__CTOR_LIST_END - . / 4 - 2)
+   *(foo)
+   __CTOR_LIST_END= .
+
+   Put these statements onto a special list.
+
+*/
+
+typedef struct constructor_list 
+{
+ldsym_type *sym;
+  struct constructor_list *next;
+}  constructor_list_type;
+   
+static constructor_list_type *constructor_name_list;
+
+void
+DEFUN(ldlang_add_constructor,(name),
+ldsym_type *name)
+{
+
+  constructor_list_type *next   = constructor_name_list;
+
+  if (name->flags & SYM_CONSTRUCTOR) return;
+
+  next = (constructor_list_type *)  ldmalloc(sizeof(constructor_list_type));
+  next->next= constructor_name_list;
+  next->sym= name;
+  name->flags |= SYM_CONSTRUCTOR;
+  constructor_name_list = next;
+}
+
+void
+DEFUN_VOID(find_constructors)
+{
+  lang_statement_list_type *old = stat_ptr;
+  constructor_list_type *p = constructor_name_list;
+  stat_ptr = & constructor_list;
+  lang_list_init(stat_ptr);
+  while (p != (constructor_list_type *)NULL) 
+      {
+       /* Have we already done this one ? */
+       CONST char *name = p->sym->name;
+       int len = strlen(name);
+       char *end = ldmalloc(len+3);
+       strcpy(end, name);
+       strcat(end,"$e");
+
+       lang_add_assignment
+         ( exp_assop('=',name, exp_nameop(NAME,".")));
+
+       lang_add_data
+         (LONG, exp_binop('-',
+                          exp_binop ( '/',
+                                     exp_binop ( '-',
+                                                exp_nameop(NAME, end),
+                                                exp_nameop(NAME,".")),
+                                     exp_intop(4)),
+
+                          exp_intop(2)));
+
+                                     
+       lang_add_wild(name, (char *)NULL);
+       lang_add_data(LONG, exp_intop(0));
+       lang_add_assignment
+         (exp_assop('=', end, exp_nameop(NAME,".")));
+p = p->next;               
+      }
+
+
+
 
+  stat_ptr = old;
+}
 void
 DEFUN_VOID(lang_process)
 {               
@@ -2016,12 +2146,15 @@ DEFUN_VOID(lang_process)
 
   common_section.userdata = (PTR)&common_section_userdata;
 
+
   /* Run through the contours of the script and attatch input sections
      to the correct output sections 
      */
+  find_constructors();
   map_input_to_output_sections(statement_list.head, (char *)NULL, 
                               ( lang_output_section_statement_type *)NULL);
 
+
   /* Find any sections not attatched explicitly and handle them */
   lang_place_orphans();
 
@@ -2189,6 +2322,13 @@ DEFUN(lang_leave_output_section_statement,(fill, memspec),
   current_section->fill = fill;
   current_section->region = lang_memory_region_lookup(memspec);
   stat_ptr = &statement_list;
+
+  /* We remember if we are closing a .data section, since we use it to
+     store constructors in */
+  if (strcmp(current_section->name, ".data") ==0) {
+   end_of_data_section_statement_list = statement_list;
+
+  }
 }
 /*
  Create an absolute symbol with the given name with the value of the
index 8705bcb7873be19434c73986ea3b1512b1f71e18..4258b523c5a3a6574a04352c17881578f994fed5 100644 (file)
@@ -101,6 +101,10 @@ boolean write_map;
 
 
 int unix_relocate;
+#ifdef GNU960
+/* Indicates whether output file will be b.out (default) or coff */
+enum target_flavour_enum output_flavor = BFD_BOUT_FORMAT;
+#endif
 
 
 
@@ -139,11 +143,23 @@ main (argc, argv)
   output_filename = "a.out";
 
 #ifdef GNU960
-  check_v960( argc, argv );
+   {
+     int i;
+     check_v960( argc, argv );
+     emulation = GLD960_EMULATION_NAME;
+     for ( i = 1; i < argc; i++ ){
+       if ( !strcmp(argv[i],"-Fcoff") ){
+       emulation = LNK960_EMULATION_NAME;
+       output_flavor = BFD_COFF_FORMAT;
+       break;
+       }
+     }
+   }
+#else
+   emulation =  (char *) getenv(EMULATION_ENVIRON); 
 #endif
 
-  emulation =  (char *) getenv(EMULATION_ENVIRON); 
-
   /* Initialize the data about options.  */
 
   trace_files = false;
@@ -168,17 +184,13 @@ main (argc, argv)
 
   config.magic_demand_paged = true ;
   config.make_executable = true;
-
-#ifdef GNU960
-  ldemul_choose_mode(LNK960_EMULATION_NAME);
-#else
   if (emulation == (char *)NULL) {
     emulation= DEFAULT_EMULATION;
   }
 
 
   ldemul_choose_mode(emulation);
-#endif
+
 
   default_target =  ldemul_choose_target();
 
@@ -239,7 +251,7 @@ Q_read_entry_symbols (desc, entry)
      struct lang_input_statement_struct *entry;
 {
   if (entry->asymbols == (asymbol **)NULL) {
-    size_t table_size = get_symtab_upper_bound(desc);
+    bfd_size_type table_size = get_symtab_upper_bound(desc);
     entry->asymbols = (asymbol **)ldmalloc(table_size);
 
     entry->symbol_count =  bfd_canonicalize_symtab(desc, entry->asymbols) ;
@@ -300,95 +312,102 @@ Q_enter_global_ref (nlist_p)
 
   ASSERT(sym->udata == 0);
 
-  /* Just place onto correct chain */
-  if (flag_is_common(this_symbol_flags)) {
-    /* If we have a definition of this symbol already then
-     * this common turns into a reference. Also we only
-     * ever point to the largest common, so if we
-     * have a common, but it's bigger that the new symbol
-     * the turn this into a reference too.
-     */
-    if (sp->sdefs_chain)  
-      {
-       /* This is a common symbol, but we already have a definition
-          for it, so just link it into the ref chain as if
-          it were a reference
-          */
-       refize(sp, nlist_p);
-      }
-    else  if (sp->scoms_chain) {
-      /* If we have a previous common, keep only the biggest */
-      if ( (*(sp->scoms_chain))->value > sym->value) {
-       /* other common is bigger, throw this one away */
-       refize(sp, nlist_p);
+  if (flag_is_constructor(this_symbol_flags))  {
+    /* Just remeber the name, do it once per name by placing it as if
+       it were a zero sized common. The next ref */
+      ldlang_add_constructor(sp);
+
+  }
+  else {  
+    if (flag_is_common(this_symbol_flags)) {
+      /* If we have a definition of this symbol already then
+       * this common turns into a reference. Also we only
+       * ever point to the largest common, so if we
+       * have a common, but it's bigger that the new symbol
+       * the turn this into a reference too.
+       */
+      if (sp->sdefs_chain)  
+         {
+           /* This is a common symbol, but we already have a definition
+              for it, so just link it into the ref chain as if
+              it were a reference
+              */
+           refize(sp, nlist_p);
+         }
+      else  if (sp->scoms_chain) {
+       /* If we have a previous common, keep only the biggest */
+       if ( (*(sp->scoms_chain))->value > sym->value) {
+         /* other common is bigger, throw this one away */
+         refize(sp, nlist_p);
+       }
+       else if (sp->scoms_chain != nlist_p) {
+         /* other common is smaller, throw that away */
+         refize(sp, sp->scoms_chain);
+         sp->scoms_chain = nlist_p;
+       }
       }
-      else if (sp->scoms_chain != nlist_p) {
-       /* other common is smaller, throw that away */
-       refize(sp, sp->scoms_chain);
+      else {
+       /* This is the first time we've seen a common, so
+        * remember it - if it was undefined before, we know it's defined now
+        */
+       if (sp->srefs_chain)
+         undefined_global_sym_count--;
+
+       commons_pending++;
        sp->scoms_chain = nlist_p;
       }
     }
-    else {
-      /* This is the first time we've seen a common, so
-       * remember it - if it was undefined before, we know it's defined now
-       */
-      if (sp->srefs_chain)
-       undefined_global_sym_count--;
 
-      commons_pending++;
-      sp->scoms_chain = nlist_p;
-    }
-  }
-
-  else if (flag_is_defined(this_symbol_flags)) {
-    /* This is the definition of a symbol, add to def chain */
-    if (sp->sdefs_chain && (*(sp->sdefs_chain))->section != sym->section) {
-      /* Multiple definition */
-      asymbol *sy = *(sp->sdefs_chain);
-      lang_input_statement_type *stat = (lang_input_statement_type *) sy->the_bfd->usrdata;
-      lang_input_statement_type *stat1 = (lang_input_statement_type *) sym->the_bfd->usrdata;
-      asymbol ** stat1_symbols  = stat1 ? stat1->asymbols: 0;
-      asymbol ** stat_symbols = stat ? stat->asymbols:0;
+    else if (flag_is_defined(this_symbol_flags)) {
+      /* This is the definition of a symbol, add to def chain */
+      if (sp->sdefs_chain && (*(sp->sdefs_chain))->section != sym->section) {
+       /* Multiple definition */
+       asymbol *sy = *(sp->sdefs_chain);
+       lang_input_statement_type *stat = (lang_input_statement_type *) sy->the_bfd->usrdata;
+       lang_input_statement_type *stat1 = (lang_input_statement_type *) sym->the_bfd->usrdata;
+       asymbol ** stat1_symbols  = stat1 ? stat1->asymbols: 0;
+       asymbol ** stat_symbols = stat ? stat->asymbols:0;
       
-      multiple_def_count++;
-      info("%C: multiple definition of `%T'\n",
-          sym->the_bfd,
-          sym->section,
-          stat1_symbols,
-          sym->value,
-          sym);
+       multiple_def_count++;
+       info("%C: multiple definition of `%T'\n",
+            sym->the_bfd,
+            sym->section,
+            stat1_symbols,
+            sym->value,
+            sym);
           
-      info("%C: first seen here\n",
-          sy->the_bfd,
-          sy->section,
-          stat_symbols,
-          sy->value);
+       info("%C: first seen here\n",
+            sy->the_bfd,
+            sy->section,
+            stat_symbols,
+            sy->value);
+      }
+      else {
+       sym->udata =(PTR)( sp->sdefs_chain);
+       sp->sdefs_chain = nlist_p;
+      }
+      /* A definition overrides a common symbol */
+      if (sp->scoms_chain) {
+       refize(sp, sp->scoms_chain);
+       sp->scoms_chain = 0;
+       commons_pending--;
+      }
+      else if (sp->srefs_chain) {
+       /* If previously was undefined, then remember as defined */
+       undefined_global_sym_count--;
+      }
     }
     else {
-      sym->udata =(PTR)( sp->sdefs_chain);
-      sp->sdefs_chain = nlist_p;
-    }
-    /* A definition overrides a common symbol */
-    if (sp->scoms_chain) {
-      refize(sp, sp->scoms_chain);
-      sp->scoms_chain = 0;
-      commons_pending--;
-    }
-    else if (sp->srefs_chain) {
-      /* If previously was undefined, then remember as defined */
-      undefined_global_sym_count--;
-    }
-  }
-  else {
-    if (sp->scoms_chain == (asymbol **)NULL 
-       && sp->srefs_chain == (asymbol **)NULL 
-       && sp->sdefs_chain == (asymbol **)NULL) {
-      /* And it's the first time we've seen it */
-      undefined_global_sym_count++;
+      if (sp->scoms_chain == (asymbol **)NULL 
+         && sp->srefs_chain == (asymbol **)NULL 
+         && sp->sdefs_chain == (asymbol **)NULL) {
+       /* And it's the first time we've seen it */
+       undefined_global_sym_count++;
 
-    }
+      }
 
-    refize(sp, nlist_p);
+      refize(sp, nlist_p);
+    }
   }
 
   ASSERT(sp->sdefs_chain == 0 || sp->scoms_chain == 0);
@@ -418,10 +437,17 @@ lang_input_statement_type *entry;
     {
       asymbol *p = *q;
 
-      if (flag_is_undefined_or_global_or_common(p->flags))
+      if (flag_is_undefined_or_global_or_common_or_constructor(p->flags))
        {
          Q_enter_global_ref(q);
        }
+      if (p->flags & BSF_INDIRECT) {
+       add_indirect(q);
+      }
+
+      if (p->flags & BSF_WARNING) {
+       add_warning(p);
+      }
       ASSERT(p->flags != 0);
     }
 }
@@ -463,9 +489,12 @@ bfd_format format;
 {
   boolean retval;
 
-  if ((bfd_check_format(abfd,format) == true) && BFD_COFF_FILE_P(abfd)) {
-       return true;
+  if ((bfd_check_format(abfd,format) == true)
+      &&  (abfd->xvec->flavour == output_flavor) ){
+    return true;
   }
+
+
   return false;
 }
 #endif
@@ -525,7 +554,7 @@ decode_library_subfile (library_entry, subfile_offset)
      bfd *subfile_offset;
 {
   register struct lang_input_statement_struct *subentry;
-  subentry = (struct lang_input_statement_struct *) ldmalloc (sizeof (struct lang_input_statement_struct));
+  subentry = (struct lang_input_statement_struct *) ldmalloc ((bfd_size_type)(sizeof (struct lang_input_statement_struct)));
   subentry->filename = subfile_offset -> filename;
   subentry->local_sym_name  = subfile_offset->filename;
   subentry->asymbols = 0;
index 2bdb7a6bd8bdee0dd44fff2c07b13958dc797702..bffa80e3665d6e79eb8d8e107c5e76633bdf0f70 100644 (file)
@@ -103,7 +103,7 @@ DEFUN(ldsym_get,(key),
   bp->sdefs_chain = (asymbol **)NULL;
   bp->scoms_chain = (asymbol **)NULL;
   bp->name = buystring(key);
-
+  bp->flags = 0;
   /* Add the entry to the bucket.  */
 
   bp->link = global_symbol_hash_table[hashval];
index 9229ea0470e042137ca083f720404aff1d6af87e..f6fc4d0af1e10f952ee62036c457d32b7e68e3d6 100644 (file)
@@ -44,6 +44,17 @@ typedef struct user_symbol_struct
    */
   asymbol **scoms_chain;
 
+  
+
+
+
+  /* If this symbol is a constructor */
+#define SYM_CONSTRUCTOR 1
+  /* If this symbol is a warning symbol */
+#define SYM_WARNING 2
+  /* IF this is an alias for another symbol */
+#define SYM_INDIRECT 4
+  int flags;
 } ldsym_type;
 
 
index be0d107125e99cc489565469efb30aa2db198534..f51ef6c6aebd7bd39343d345755b3ffceb4c8ca3 100644 (file)
@@ -19,4 +19,6 @@
    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
-PROTOX(void, ldwarn,(void));
+
+void EXFUN(add_warning,(asymbol *));
+CONST char * EXFUN(fetch_warning,(asymbol *));