aboutsummaryrefslogtreecommitdiff
path: root/ld/ldlang.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r--ld/ldlang.c150
1 files changed, 145 insertions, 5 deletions
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