From 8101605119976f94d00db43a2d78d7fb341a7680 Mon Sep 17 00:00:00 2001 From: Steve Chamberlain Date: Thu, 1 Aug 1991 23:29:23 +0000 Subject: [PATCH] Added new keyword 'CONSTRUCTORS' Added N_WARNING handling Added N_INDR handling --- ld/ldgld.script | 24 +++--- ld/ldgldUr.script | 9 +- ld/ldlang.c | 150 ++++++++++++++++++++++++++++++-- ld/ldmain.c | 211 ++++++++++++++++++++++++++-------------------- ld/ldsym.c | 2 +- ld/ldsym.h | 11 +++ ld/ldwarn.h | 4 +- 7 files changed, 294 insertions(+), 117 deletions(-) diff --git a/ld/ldgld.script b/ld/ldgld.script index 2f402c1324f..15ff71fc383 100755 --- a/ld/ldgld.script +++ b/ld/ldgld.script @@ -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 = .; } } diff --git a/ld/ldgldUr.script b/ld/ldgldUr.script index 3871454f8d3..e7d9b447051 100755 --- a/ld/ldgldUr.script +++ b/ld/ldgldUr.script @@ -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) : diff --git a/ld/ldlang.c b/ld/ldlang.c index 1ffad73e504..5a65b0ee45b 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -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 diff --git a/ld/ldmain.c b/ld/ldmain.c index 8705bcb7873..4258b523c5a 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -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; diff --git a/ld/ldsym.c b/ld/ldsym.c index 2bdb7a6bd8b..bffa80e3665 100644 --- a/ld/ldsym.c +++ b/ld/ldsym.c @@ -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]; diff --git a/ld/ldsym.h b/ld/ldsym.h index 9229ea0470e..f6fc4d0af1e 100644 --- a/ld/ldsym.h +++ b/ld/ldsym.h @@ -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; diff --git a/ld/ldwarn.h b/ld/ldwarn.h index be0d107125e..f51ef6c6aeb 100644 --- a/ld/ldwarn.h +++ b/ld/ldwarn.h @@ -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 *)); -- 2.30.2