aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
Diffstat (limited to 'ld')
-rwxr-xr-xld/ldgld.script24
-rwxr-xr-xld/ldgldUr.script9
-rw-r--r--ld/ldlang.c150
-rw-r--r--ld/ldmain.c211
-rw-r--r--ld/ldsym.c2
-rw-r--r--ld/ldsym.h11
-rw-r--r--ld/ldwarn.h4
7 files changed, 294 insertions, 117 deletions
diff --git a/ld/ldgld.script b/ld/ldgld.script
index 2f402c1..15ff71f 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 3871454..e7d9b44 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 1ffad73..5a65b0e 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 8705bcb..4258b52 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 2bdb7a6..bffa80e 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 9229ea0..f6fc4d0 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 be0d107..f51ef6c 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 *));